feat: use network instead of parent-container

This commit is contained in:
fengcaiwen
2023-03-16 15:21:08 +08:00
committed by wencaiwulue
parent 321a63ab96
commit ac3c7c218f
12 changed files with 109 additions and 52 deletions

View File

@@ -89,7 +89,7 @@ container:
############################ build local
.PHONY: container-local
container-local: kubevpn-linux-amd64
docker buildx build --platform linux/amd64 -t docker.io/naison/kubevpn:latest -f $(BUILD_DIR)/local.Dockerfile .
docker buildx build --platform linux/amd64 -t docker.io/naison/kubevpn:latest -f $(BUILD_DIR)/local.Dockerfile --push .
.PHONY: container-test
container-test: kubevpn-linux-amd64

View File

@@ -333,7 +333,7 @@ as `--entrypoint "tail -f /dev/null"`, for more parameters, see `kubevpn dev --h
If you want to start the development mode locally using Docker in Docker (DinD), because 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
need to special parameter `--network` (inner docker) for sharing network and pid
Example:
@@ -345,7 +345,7 @@ docker run -it --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /tmp
➜ ~ 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"
root@4d0c3c4eae2b:/# kubevpn dev deployment/authors -n kube-system --image naison/kubevpn:v1.1.21 --headers user=naison --network container:4d0c3c4eae2b --entrypoint "tail -f /dev/null"
----------------------------------------------------------------------------------
Warn: Use sudo to execute command kubevpn can not use user env KUBECONFIG.
@@ -507,7 +507,7 @@ pod [kubevpn-traffic-manager] status is Running
...
```
- When use kubevpn dev, but got error code 137, how to resolve ?
- When use `kubevpn dev`, but got error code 137, how to resolve ?
```text
dns service ok
@@ -527,3 +527,15 @@ clean up successful
This is because of your docker-desktop required resource is less than pod running request resource, it OOM killed, so
you can add more resource in your docker-desktop setting `Preferences --> Resources --> Memory`
- I am using WSL( Windows Sub Linux ) Docker, when use mode `kubevpn dev`, can not connect to cluster network, how to
solve this problem?
Answer: this is because WSL'Docker using Windows's Network, so if even start a container in WSL, this container will
not use WSL network, but use Windows network
Solution:
- 1): install docker in WSL, not use Windows Docker-desktop
- 2): use command `kubevpn connect` on Windows, and then startup `kubevpn dev` in WSL
- 3): startup a container using command `kubevpn connect` on Windows, and then
startup `kubevpn dev --network container:$CONTAINER_ID` in WSL

View File

@@ -325,7 +325,7 @@ de9e2f8ab57d nginx:latest "/docker-entrypoint.…" 5 seconds
### DinD ( Docker in Docker ) 在 Docker 中使用 kubevpn
如果你想在本地使用 Docker in Docker (DinD) 的方式启动开发模式, 由于程序会读写 `/tmp` 目录,您需要手动添加参数 `-v /tmp:/tmp`, 还有一点需要注意, 如果使用 DinD
模式,为了共享容器网络和 pid, 还需要指定参数 `--parent-container`
模式,为了共享容器网络和 pid, 还需要指定参数 `--network`
例如:
@@ -337,7 +337,7 @@ docker run -it --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /tmp
➜ ~ 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"
root@4d0c3c4eae2b:/# kubevpn dev deployment/authors -n kube-system --image naison/kubevpn:v1.1.21 --headers user=naison --network container:4d0c3c4eae2b --entrypoint "tail -f /dev/null"
----------------------------------------------------------------------------------
Warn: Use sudo to execute command kubevpn can not use user env KUBECONFIG.
@@ -517,3 +517,13 @@ clean up successful
这是因为你的 `Docker-desktop` 声明的资源, 小于 container 容器启动时所需要的资源, 因此被 OOM 杀掉了, 你可以增加 `Docker-desktop` 对于 resources
的设置, 目录是:`Preferences --> Resources --> Memory`
- 我在使用 WSL( Windows Sub Linux ) Docker, 当我在使用命令 `kubevpn dev` 进入开发模式的时候, 在 terminal 中无法提示链接集群网络, 这是为什么, 如何解决?
答案: 这是因为 WSL 的 Docker 使用的是 主机 Windows 的网络, 所以即便在 WSL 中启动 container, 这个 container 不会使用 WSL 的网络,而是使用 Windows 的网络。
解决方案:
- 1): 在 WSL 中安装 Docker, 不要使用 Windows 版本的 Docker-desktop
- 2): 在主机 Windows 使用命令 `kubevpn connect`, 然后在 WSL 中使用 `kubevpn dev` 进入开发模式
- 3): 在主机 Windows 上启动一个 container在 container 中使用命令 `kubevpn connect`, 然后在 WSL
中使用 `kubevpn dev --network container:$CONTAINER_ID`

View File

@@ -16,7 +16,7 @@ ARG BASE=github.com/wencaiwulue/kubevpn
RUN sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
&& sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean && apt-get update && apt-get install -y wget dnsutils vim curl \
net-tools iptables iputils-ping lsof iproute2 tcpdump binutils
net-tools iptables iputils-ping lsof iproute2 tcpdump binutils traceroute
WORKDIR /app

View File

@@ -4,7 +4,7 @@ FROM ubuntu:latest
RUN sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
&& sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean && apt-get update && apt-get install -y wget dnsutils vim curl \
net-tools iptables iputils-ping lsof iproute2 tcpdump binutils
net-tools iptables iputils-ping lsof iproute2 tcpdump binutils traceroute
WORKDIR /app

View File

@@ -10,6 +10,7 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
@@ -32,26 +33,30 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
Env: opts.NewListOpts(nil),
Volumes: opts.NewListOpts(nil),
ExtraHosts: opts.NewListOpts(nil),
Aliases: opts.NewListOpts(nil),
NoProxy: false,
ExtraCIDR: []string{},
}
var sshConf = &util.SshConfig{}
cmd := &cobra.Command{
Use: "dev",
Short: i18n.T("Proxy kubernetes workloads inbound traffic into local PC and dev in docker container"),
Long: templates.LongDesc(i18n.T(`Proxy kubernetes workloads inbound traffic into local PC`)),
Short: i18n.T("Startup your workloads in local Docker container use same volume、env、and network with cluster"),
Long: templates.LongDesc(i18n.T(`Startup your workloads in local Docker container use same volume、env、and network with cluster`)),
Example: templates.Examples(i18n.T(`
# Dev reverse proxy
- reverse deployment
# Develop workloads
- develop deployment
kubevpn dev deployment/productpage
- reverse service
- develop service
kubevpn dev service/productpage
# Reverse proxy with mesh, traffic with header a=1, will hit local PC, otherwise no effect
# Develop workloads with mesh, traffic with header a=1, will hit local PC, otherwise no effect
kubevpn dev service/productpage --headers a=1
# Dev reverse proxy api-server behind of bastion host or ssh jump host
# Develop workloads without proxy traffic
kubevpn dev service/productpage --no-proxy
# Develop workloads which api-server behind of bastion host or ssh jump host
kubevpn dev deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile /Users/naison/.ssh/ssh.pem
# it also support ProxyJump, like
@@ -78,13 +83,14 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
ExtraCIDR: devOptions.ExtraCIDR,
}
if devOptions.ParentContainer != "" {
mode := container.NetworkMode(devOptions.NetMode.NetworkMode())
if mode.IsContainer() {
client, _, err := dev.GetClient()
if err != nil {
return err
}
var inspect types.ContainerJSON
inspect, err = client.ContainerInspect(context.Background(), devOptions.ParentContainer)
inspect, err = client.ContainerInspect(context.Background(), mode.ConnectedContainer())
if err != nil {
return err
}
@@ -92,7 +98,7 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
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)
return fmt.Errorf("container %s status is %s, expect is running, please make sure your outer docker name is correct", mode.ConnectedContainer(), inspect.State.Status)
}
}
@@ -145,7 +151,15 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
// docker options
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().StringVar(&devOptions.ParentContainer, "parent-container", "", "Parent container name if running in Docker (Docker in Docker)")
// We allow for both "--net" and "--network", although the latter is the recommended way.
cmd.Flags().Var(&devOptions.NetMode, "net", "Connect a container to a network")
cmd.Flags().Var(&devOptions.NetMode, "network", "Connect a container to a network")
cmd.Flags().MarkHidden("net")
// We allow for both "--net-alias" and "--network-alias", although the latter is the recommended way.
cmd.Flags().Var(&devOptions.Aliases, "net-alias", "Add network-scoped alias for the container")
cmd.Flags().Var(&devOptions.Aliases, "network-alias", "Add network-scoped alias for the container")
cmd.Flags().MarkHidden("net-alias")
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.Expose, "expose", "Expose a port or a range of ports")

View File

@@ -28,26 +28,29 @@ func CmdDuplicate(f cmdutil.Factory) *cobra.Command {
var sshConf = &util.SshConfig{}
cmd := &cobra.Command{
Use: "duplicate",
Short: i18n.T("Connect to kubernetes cluster network, and duplicate workloads to target-kubeconfig cluster with same volume、env、and network"),
Long: templates.LongDesc(i18n.T(`Connect to kubernetes cluster network, and duplicate workloads to target-kubeconfig cluster with same volume、env、and network`)),
Short: i18n.T("Duplicate workloads to target-kubeconfig cluster with same volume、env、and network"),
Long: templates.LongDesc(i18n.T(`Duplicate workloads to target-kubeconfig cluster with same volume、env、and network`)),
Example: templates.Examples(i18n.T(`
# duplicate
- duplicate deployment
- duplicate deployment in current cluster and current namespace
kubevpn duplicate deployment/productpage
- duplicate service
kubevpn proxy service/productpage
- duplicate deployment in current cluster with different namespace
kubevpn duplicate deployment/productpage -n test
- duplicate deployment to another cluster
kubevpn duplicate deployment/productpage --target-kubeconfig ~/.kube/other-kubeconfig
- duplicate multiple workloads
kubevpn duplicate deployment/authors deployment/productpage
or
kubevpn duplicate deployment authors productpage
# Reverse duplicate with mesh, traffic with header a=1, will hit local PC, otherwise no effect
kubevpn duplicate service/productpage --headers a=1
# duplicate with mesh, traffic with header a=1, will hit duplicate workloads, otherwise hit origin workloads
kubevpn duplicate deployment/productpage --headers a=1
# Connect to api-server behind of bastion host or ssh jump host and proxy kubernetes resource traffic into local PC
kubevpn duplicate --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile /Users/naison/.ssh/ssh.pem service/productpage --headers a=1
# duplicate workloads which api-server behind of bastion host or ssh jump host
kubevpn duplicate deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile /Users/naison/.ssh/ssh.pem --headers a=1
# it also support ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐

View File

@@ -25,8 +25,8 @@ func CmdProxy(f cmdutil.Factory) *cobra.Command {
var sshConf = &util.SshConfig{}
cmd := &cobra.Command{
Use: "proxy",
Short: i18n.T("Connect to kubernetes cluster network and proxy kubernetes workloads inbound traffic into local PC"),
Long: templates.LongDesc(i18n.T(`Connect to kubernetes cluster network, or proxy kubernetes workloads inbound traffic into local PC`)),
Short: i18n.T("Proxy kubernetes workloads inbound traffic into local PC"),
Long: templates.LongDesc(i18n.T(`Proxy kubernetes workloads inbound traffic into local PC`)),
Example: templates.Examples(i18n.T(`
# Reverse proxy
- proxy deployment
@@ -44,7 +44,7 @@ func CmdProxy(f cmdutil.Factory) *cobra.Command {
kubevpn proxy service/productpage --headers a=1
# Connect to api-server behind of bastion host or ssh jump host and proxy kubernetes resource traffic into local PC
kubevpn proxy --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile /Users/naison/.ssh/ssh.pem service/productpage --headers a=1
kubevpn proxy deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile /Users/naison/.ssh/ssh.pem --headers a=1
# it also support ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐

View File

@@ -7,10 +7,11 @@ import (
"fmt"
"io"
"os"
"runtime"
"strings"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest"
@@ -52,7 +53,10 @@ func extractFileSpec(arg string) (fileSpec, error) {
if i == 0 {
return fileSpec{}, errFileSpecDoesntMatchFormat
}
if i == -1 {
// C:\Users\ADMINI~1\AppData\Local\Temp\849198392506502457
// disk name C is not a pod name
if i == -1 || (runtime.GOOS == "windows" && strings.Contains("ABCDEFGHIJKLMNOPQRSTUVWXYZ", arg[:i])) {
return fileSpec{
File: newLocalPath(arg),
}, nil
@@ -178,7 +182,9 @@ func (o *CopyOptions) copyToPod(src, dest fileSpec, options *exec.ExecOptions) e
go func(src localPath, dest remotePath, writer io.WriteCloser) {
defer writer.Close()
cmdutil.CheckErr(makeTar(src, dest, writer))
if err := makeTar(src, dest, writer); err != nil {
log.Error(err)
}
}(srcFile, destFile, writer)
var cmdArr []string
@@ -259,7 +265,9 @@ func (t *TarPipe) initReadFrom(n uint64) {
go func() {
defer t.outStream.Close()
cmdutil.CheckErr(t.o.execute(options))
if err := t.o.execute(options); err != nil {
log.Error(err)
}
}()
}

View File

@@ -13,6 +13,7 @@ import (
"github.com/docker/cli/cli/flags"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/mount"
"github.com/docker/docker/client"
@@ -49,7 +50,8 @@ type Options struct {
Publish opts.ListOpts
Expose opts.ListOpts
ExtraHosts opts.ListOpts
ParentContainer string
NetMode opts.NetworkOpt
Aliases opts.ListOpts
Env opts.ListOpts
Mounts opts.MountOpt
Volumes opts.ListOpts
@@ -124,12 +126,15 @@ func (d Options) Main(ctx context.Context) error {
if outOfMemory {
return fmt.Errorf("your pod resource request is bigger than docker-desktop resource, please adjust your docker-desktop resource")
}
if d.ParentContainer != "" {
mode := container.NetworkMode(d.NetMode.NetworkMode())
if mode.IsUserDefined() {
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.NetworkMode = mode
if mode.IsContainer() {
config.hostConfig.PidMode = containertypes.PidMode(d.NetMode.NetworkMode())
}
config.hostConfig.PortBindings = nil
// remove dns

View File

@@ -148,6 +148,11 @@ func fillOptions(r Run, copts Options) error {
config.hostConfig.Binds = binds
// todo
if copts.Aliases.Len() != 0 {
//config.networkingConfig.EndpointsConfig
}
return nil
}

View File

@@ -146,7 +146,7 @@ func GetVolume(ctx context.Context, f util.Factory, ns, pod string) (map[string]
}
err = copyOptions.Run()
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "Can not download volume %s path %s, err: %v, ignore...\n", volumeMount.Name, volumeMount.MountPath, err)
_, _ = fmt.Fprintf(os.Stderr, "failed to download volume %s path %s to %s, err: %v, ignore...\n", volumeMount.Name, remotePath, join, err)
continue
}
m = append(m, mount.Mount{