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"
@@ -43,17 +44,18 @@ type Options struct {
// docker options
Platform string
//Pull string // always, missing, never
PublishAll bool
Entrypoint string
DockerImage string
Publish opts.ListOpts
Expose opts.ListOpts
ExtraHosts opts.ListOpts
ParentContainer string
Env opts.ListOpts
Mounts opts.MountOpt
Volumes opts.ListOpts
VolumeDriver string
PublishAll bool
Entrypoint string
DockerImage string
Publish opts.ListOpts
Expose opts.ListOpts
ExtraHosts opts.ListOpts
NetMode opts.NetworkOpt
Aliases opts.ListOpts
Env opts.ListOpts
Mounts opts.MountOpt
Volumes opts.ListOpts
VolumeDriver string
}
func (d Options) Main(ctx context.Context) error {
@@ -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{