refactor: rename cmd dev to run (#684)

* refactor: code

* refactor: optimize code
This commit is contained in:
naison
2025-08-04 23:00:38 +08:00
committed by GitHub
parent 2d5653ee2b
commit b3b13fce86
21 changed files with 110 additions and 104 deletions

View File

@@ -137,9 +137,7 @@ Forwarding port...
Connected tunnel Connected tunnel
Adding route... Adding route...
Configured DNS service Configured DNS service
+----------------------------------------------------------+ Now you can access resources in the kubernetes cluster !
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~ ➜ ~
``` ```
@@ -270,9 +268,7 @@ Forwarding port...
Connected tunnel Connected tunnel
Adding route... Adding route...
Configured DNS service Configured DNS service
+----------------------------------------------------------+ Now you can access resources in the kubernetes cluster !
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
``` ```
use command `kubevpn status` to check connection status use command `kubevpn status` to check connection status
@@ -297,9 +293,7 @@ Checking rollout status for deployment/productpage
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Rollout successfully for deployment/productpage Rollout successfully for deployment/productpage
+----------------------------------------------------------+ Now you can access resources in the kubernetes cluster !
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~ ➜ ~
``` ```
@@ -398,9 +392,7 @@ Checking rollout status for deployment/productpage
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Rollout successfully for deployment/productpage Rollout successfully for deployment/productpage
+----------------------------------------------------------+ Now you can access resources in the kubernetes cluster !
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~ ➜ ~
``` ```
@@ -456,7 +448,7 @@ Run the Kubernetes pod in the local Docker container, and cooperate with the ser
the specified header to the local, or all the traffic to the local. the specified header to the local, or all the traffic to the local.
```shell ```shell
➜ ~ kubevpn dev deployment/authors --headers foo=bar --entrypoint sh ➜ ~ kubevpn run deployment/authors --headers foo=bar --entrypoint sh
Starting connect Starting connect
Got network CIDR from cache Got network CIDR from cache
Use exist traffic manager Use exist traffic manager
@@ -551,13 +543,13 @@ docker logs $(docker ps --format '{{.Names}}' | grep nginx_default_kubevpn)
If you just want to start up a docker image, you can use a simple way like this: If you just want to start up a docker image, you can use a simple way like this:
```shell ```shell
kubevpn dev deployment/authors --no-proxy kubevpn run deployment/authors --no-proxy
``` ```
Example Example
```shell ```shell
➜ ~ kubevpn dev deployment/authors --no-proxy ➜ ~ kubevpn run deployment/authors --no-proxy
Starting connect Starting connect
Got network CIDR from cache Got network CIDR from cache
Use exist traffic manager Use exist traffic manager
@@ -585,7 +577,7 @@ Now the main process will hang up to show you log.
If you want to specify the image to start the container locally, you can use the parameter `--dev-image`. When the If you want to specify the image to start the container locally, you can use the parameter `--dev-image`. When the
image does not exist locally, it will be pulled from the corresponding mirror warehouse. If you want to specify startup 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 parameters, you can use `--entrypoint` parameter, replace it with the command you want to execute, such
as `--entrypoint /bin/bash`, for more parameters, see `kubevpn dev --help`. as `--entrypoint /bin/bash`, for more parameters, see `kubevpn run --help`.
### DinD ( Docker in Docker ) use kubevpn in Docker ### DinD ( Docker in Docker ) use kubevpn in Docker
@@ -616,7 +608,7 @@ ca82aef6a9eb: Pull complete
Digest: sha256:368db2e0d98f6866dcefd60512960ce1310e85c24a398fea2a347905ced9507d Digest: sha256:368db2e0d98f6866dcefd60512960ce1310e85c24a398fea2a347905ced9507d
Status: Downloaded newer image for ghcr.io/kubenetworks/kubevpn:latest Status: Downloaded newer image for ghcr.io/kubenetworks/kubevpn:latest
WARNING: image with reference ghcr.io/kubenetworks/kubevpn was found but does not match the specified platform: wanted linux/amd64, actual: linux/arm64 WARNING: image with reference ghcr.io/kubenetworks/kubevpn was found but does not match the specified platform: wanted linux/amd64, actual: linux/arm64
root@5732124e6447:/app# kubevpn dev deployment/authors --headers user=naison --entrypoint sh root@5732124e6447:/app# kubevpn run deployment/authors --headers user=naison --entrypoint sh
hostname is 5732124e6447 hostname is 5732124e6447
Starting connect Starting connect
Got network CIDR from cache Got network CIDR from cache
@@ -645,7 +637,7 @@ Created main container: authors_default_kubevpn_6df5f
/opt/microservices # ps -ef /opt/microservices # ps -ef
PID USER TIME COMMAND PID USER TIME COMMAND
1 root 0:00 {bash} /usr/bin/qemu-x86_64 /bin/bash /bin/bash 1 root 0:00 {bash} /usr/bin/qemu-x86_64 /bin/bash /bin/bash
14 root 0:02 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn kubevpn dev deployment/authors --headers 14 root 0:02 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn kubevpn run deployment/authors --headers
25 root 0:01 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon 25 root 0:01 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon
37 root 0:04 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon --sudo 37 root 0:04 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon --sudo
53 root 0:00 nginx: master process nginx -g daemon off; 53 root 0:00 nginx: master process nginx -g daemon off;

View File

@@ -125,9 +125,7 @@ Forwarding port...
Connected tunnel Connected tunnel
Adding route... Adding route...
Configured DNS service Configured DNS service
+----------------------------------------------------------+ Now you can access resources in the kubernetes cluster !
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~ ➜ ~
``` ```
@@ -253,9 +251,7 @@ Forwarding port...
Connected tunnel Connected tunnel
Adding route... Adding route...
Configured DNS service Configured DNS service
+----------------------------------------------------------+ Now you can access resources in the kubernetes cluster !
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
``` ```
使用命令 `kubevpn status` 查看当前链接状态。 使用命令 `kubevpn status` 查看当前链接状态。
@@ -282,9 +278,7 @@ Checking rollout status for deployment/productpage
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Rollout successfully for deployment/productpage Rollout successfully for deployment/productpage
+----------------------------------------------------------+ Now you can access resources in the kubernetes cluster !
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~ ➜ ~
``` ```
@@ -341,9 +335,7 @@ Checking rollout status for deployment/productpage
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Rollout successfully for deployment/productpage Rollout successfully for deployment/productpage
+----------------------------------------------------------+ Now you can access resources in the kubernetes cluster !
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~ ➜ ~
``` ```
@@ -398,7 +390,7 @@ Rollout successfully for deployments/productpage
Docker。 Docker。
```shell ```shell
➜ ~ kubevpn dev deployment/authors --headers foo=bar --entrypoint sh ➜ ~ kubevpn run deployment/authors --headers foo=bar --entrypoint sh
Starting connect Starting connect
Got network CIDR from cache Got network CIDR from cache
Use exist traffic manager Use exist traffic manager
@@ -478,13 +470,13 @@ fc04e42799a5 nginx:latest "/docker-entrypoint.…" 37 sec
如果你只是想在本地启动镜像,可以用一种简单的方式: 如果你只是想在本地启动镜像,可以用一种简单的方式:
```shell ```shell
kubevpn dev deployment/authors --no-proxy kubevpn run deployment/authors --no-proxy
``` ```
例如: 例如:
```shell ```shell
➜ ~ kubevpn dev deployment/authors --no-proxy ➜ ~ kubevpn run deployment/authors --no-proxy
Starting connect Starting connect
Got network CIDR from cache Got network CIDR from cache
Use exist traffic manager Use exist traffic manager
@@ -511,7 +503,7 @@ Created main container: authors_default_kubevpn_ff34b
如果你想指定在本地启动容器的镜像, 可以使用参数 `--dev-image`, 当本地不存在该镜像时, 如果你想指定在本地启动容器的镜像, 可以使用参数 `--dev-image`, 当本地不存在该镜像时,
会从对应的镜像仓库拉取。如果你想指定启动参数,可以使用 `--entrypoint` 会从对应的镜像仓库拉取。如果你想指定启动参数,可以使用 `--entrypoint`
参数,替换为你想要执行的命令,比如 `--entrypoint /bin/bash`, 更多使用参数,请参见 `kubevpn dev --help`. 参数,替换为你想要执行的命令,比如 `--entrypoint /bin/bash`, 更多使用参数,请参见 `kubevpn run --help`.
### DinD ( Docker in Docker ) 在 Docker 中使用 kubevpn ### DinD ( Docker in Docker ) 在 Docker 中使用 kubevpn
@@ -541,7 +533,7 @@ ca82aef6a9eb: Pull complete
Digest: sha256:368db2e0d98f6866dcefd60512960ce1310e85c24a398fea2a347905ced9507d Digest: sha256:368db2e0d98f6866dcefd60512960ce1310e85c24a398fea2a347905ced9507d
Status: Downloaded newer image for ghcr.io/kubenetworks/kubevpn:latest Status: Downloaded newer image for ghcr.io/kubenetworks/kubevpn:latest
WARNING: image with reference ghcr.io/kubenetworks/kubevpn was found but does not match the specified platform: wanted linux/amd64, actual: linux/arm64 WARNING: image with reference ghcr.io/kubenetworks/kubevpn was found but does not match the specified platform: wanted linux/amd64, actual: linux/arm64
root@5732124e6447:/app# kubevpn dev deployment/authors --headers user=naison --entrypoint sh root@5732124e6447:/app# kubevpn run deployment/authors --headers user=naison --entrypoint sh
hostname is 5732124e6447 hostname is 5732124e6447
Starting connect Starting connect
Got network CIDR from cache Got network CIDR from cache
@@ -570,7 +562,7 @@ Created main container: authors_default_kubevpn_6df5f
/opt/microservices # ps -ef /opt/microservices # ps -ef
PID USER TIME COMMAND PID USER TIME COMMAND
1 root 0:00 {bash} /usr/bin/qemu-x86_64 /bin/bash /bin/bash 1 root 0:00 {bash} /usr/bin/qemu-x86_64 /bin/bash /bin/bash
14 root 0:02 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn kubevpn dev deployment/authors --headers 14 root 0:02 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn kubevpn run deployment/authors --headers
25 root 0:01 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon 25 root 0:01 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon
37 root 0:04 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon --sudo 37 root 0:04 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon --sudo
53 root 0:00 nginx: master process nginx -g daemon off; 53 root 0:00 nginx: master process nginx -g daemon off;

View File

@@ -124,7 +124,7 @@ func CmdConnect(f cmdutil.Factory) *cobra.Command {
return err return err
} }
if !foreground { if !foreground {
util.Print(os.Stdout, config.Slogan) _, _ = fmt.Fprintln(os.Stdout, config.Slogan)
} else { } else {
<-cmd.Context().Done() <-cmd.Context().Done()
err = disconnect(cli, bytes, ns, sshConf) err = disconnect(cli, bytes, ns, sshConf)

View File

@@ -13,7 +13,6 @@ import (
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon" "github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc" "github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
) )
func CmdConnection(f cmdutil.Factory) *cobra.Command { func CmdConnection(f cmdutil.Factory) *cobra.Command {
@@ -27,7 +26,6 @@ func CmdConnection(f cmdutil.Factory) *cobra.Command {
} }
func cmdConnectionList(f cmdutil.Factory) *cobra.Command { func cmdConnectionList(f cmdutil.Factory) *cobra.Command {
var sshConf = &pkgssh.SshConfig{}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "list", Use: "list",
Short: i18n.T("List all connections"), Short: i18n.T("List all connections"),
@@ -59,7 +57,6 @@ func cmdConnectionList(f cmdutil.Factory) *cobra.Command {
return nil return nil
}, },
} }
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
return cmd return cmd
} }

View File

@@ -2,6 +2,7 @@ package cmds
import ( import (
"context" "context"
"fmt"
"os" "os"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@@ -58,10 +59,10 @@ func CmdProxy(f cmdutil.Factory) *cobra.Command {
kubevpn proxy deployment authors productpage kubevpn proxy deployment authors productpage
# Reverse proxy with mesh, traffic with header foo=bar, will hit local PC, otherwise no effect # Reverse proxy with mesh, traffic with header foo=bar, will hit local PC, otherwise no effect
kubevpn proxy service/productpage --headers foo=bar kubevpn proxy deployment/productpage --headers foo=bar
# Reverse proxy with mesh, traffic with header foo=bar and env=dev, will hit local PC, otherwise no effect # Reverse proxy with mesh, traffic with header foo=bar and env=dev, will hit local PC, otherwise no effect
kubevpn proxy service/productpage --headers foo=bar --headers env=dev kubevpn proxy deployment/productpage --headers foo=bar --headers env=dev
# Connect to api-server behind of bastion host or ssh jump host and proxy kubernetes resource traffic into local PC # Connect to api-server behind of bastion host or ssh jump host and proxy kubernetes resource traffic into local PC
kubevpn proxy deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem --headers foo=bar kubevpn proxy deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem --headers foo=bar
@@ -70,12 +71,12 @@ func CmdProxy(f cmdutil.Factory) *cobra.Command {
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │ │ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘ └──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
kubevpn proxy service/productpage --ssh-alias <alias> --headers foo=bar kubevpn proxy deployment/productpage --ssh-alias <alias> --headers foo=bar
# Support ssh auth GSSAPI # Support ssh auth GSSAPI
kubevpn proxy service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab kubevpn proxy deployment/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab
kubevpn proxy service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache kubevpn proxy deployment/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache
kubevpn proxy service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD> kubevpn proxy deployment/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD>
# Support port map, you can proxy container port to local port by command: # Support port map, you can proxy container port to local port by command:
kubevpn proxy deployment/productpage --portmap 80:8080 kubevpn proxy deployment/productpage --portmap 80:8080
@@ -145,7 +146,7 @@ func CmdProxy(f cmdutil.Factory) *cobra.Command {
} }
return err return err
} }
util.Print(os.Stdout, config.Slogan) _, _ = fmt.Fprintln(os.Stdout, config.Slogan)
// hangup // hangup
if foreground { if foreground {
// leave from cluster resources // leave from cluster resources

View File

@@ -58,8 +58,7 @@ func NewKubeVPNCommand() *cobra.Command {
CmdLeave(factory), CmdLeave(factory),
CmdSync(factory), CmdSync(factory),
CmdUnsync(factory), CmdUnsync(factory),
CmdDev(factory), CmdRun(factory),
CmdConnection(factory),
// Hidden, Server Commands (DO NOT USE IT !!!) // Hidden, Server Commands (DO NOT USE IT !!!)
CmdControlPlane(factory), CmdControlPlane(factory),
CmdServer(factory), CmdServer(factory),

View File

@@ -12,16 +12,16 @@ import (
"github.com/wencaiwulue/kubevpn/v2/pkg/config" "github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon" "github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/dev"
"github.com/wencaiwulue/kubevpn/v2/pkg/handler" "github.com/wencaiwulue/kubevpn/v2/pkg/handler"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log" plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
"github.com/wencaiwulue/kubevpn/v2/pkg/run"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh" pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
"github.com/wencaiwulue/kubevpn/v2/pkg/util" "github.com/wencaiwulue/kubevpn/v2/pkg/util"
"github.com/wencaiwulue/kubevpn/v2/pkg/util/regctl" "github.com/wencaiwulue/kubevpn/v2/pkg/util/regctl"
) )
func CmdDev(f cmdutil.Factory) *cobra.Command { func CmdRun(f cmdutil.Factory) *cobra.Command {
var options = &dev.Options{ var options = &run.Options{
NoProxy: false, NoProxy: false,
ExtraRouteInfo: handler.ExtraRouteInfo{}, ExtraRouteInfo: handler.ExtraRouteInfo{},
} }
@@ -31,9 +31,9 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
var managerNamespace string var managerNamespace string
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "dev TYPE/NAME [-c CONTAINER] [flags] -- [args...]", Use: "dev TYPE/NAME [-c CONTAINER] [flags] -- [args...]",
Short: i18n.T("Startup your kubernetes workloads in local Docker container"), Short: i18n.T("Run kubernetes workloads in local Docker container"),
Long: templates.LongDesc(i18n.T(` Long: templates.LongDesc(i18n.T(`
Startup your kubernetes workloads in local Docker container with same volumeenvand network Run kubernetes workloads in local Docker container with same volumeenvand network
## What did it do: ## What did it do:
- Download volume which MountPath point to, mount to docker container - Download volume which MountPath point to, mount to docker container
@@ -41,36 +41,34 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
- Get all environment with command (env), set env to docker container - Get all environment with command (env), set env to docker container
`)), `)),
Example: templates.Examples(i18n.T(` Example: templates.Examples(i18n.T(`
# Develop workloads # Run workloads
- develop deployment - run deployment
kubevpn dev deployment/productpage kubevpn run deployment/productpage
- develop service
kubevpn dev service/productpage
# Develop workloads with mesh, traffic with header foo=bar, will hit local PC, otherwise no effect # Run workloads with mesh, traffic with header foo=bar, will hit local PC, otherwise no effect
kubevpn dev service/productpage --headers foo=bar kubevpn run deployment/productpage --headers foo=bar
# Develop workloads without proxy traffic # Run workloads without proxy traffic
kubevpn dev service/productpage --no-proxy kubevpn run deployment/productpage --no-proxy
# Develop workloads which api-server behind of bastion host or ssh jump host # Run 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 ~/.ssh/ssh.pem kubevpn run deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem
# It also supports ProxyJump, like # It also supports ProxyJump, like
pc ssh1 ssh2 ssh3 ... api-server pc ssh1 ssh2 ssh3 ... api-server
kubevpn dev deployment/productpage --ssh-alias <alias> kubevpn run deployment/productpage --ssh-alias <alias>
# Switch to terminal mode; send stdin to 'bash' and sends stdout/stderror from 'bash' back to the client # Switch to terminal mode; send stdin to 'bash' and sends stdout/stderror from 'bash' back to the client
kubevpn dev deployment/authors -n default --kubeconfig ~/.kube/config --ssh-alias dev --entrypoint /bin/bash kubevpn run deployment/authors -n default --kubeconfig ~/.kube/config --ssh-alias dev --entrypoint /bin/bash
or or
kubevpn dev deployment/authors -n default --kubeconfig ~/.kube/config --ssh-alias dev --entrypoint /bin/bash kubevpn run deployment/authors -n default --kubeconfig ~/.kube/config --ssh-alias dev --entrypoint /bin/bash
# Support ssh auth GSSAPI # Support ssh auth GSSAPI
kubevpn dev deployment/authors -n default --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab --entrypoint /bin/bash kubevpn run deployment/authors -n default --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab --entrypoint /bin/bash
kubevpn dev deployment/authors -n default --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache --entrypoint /bin/bash kubevpn run deployment/authors -n default --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache --entrypoint /bin/bash
kubevpn dev deployment/authors -n default --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD> --entrypoint /bin/bash kubevpn run deployment/authors -n default --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD> --entrypoint /bin/bash
`)), `)),
ValidArgsFunction: completion.ResourceTypeAndNameCompletionFunc(f), ValidArgsFunction: completion.ResourceTypeAndNameCompletionFunc(f),
Args: cobra.MatchAll(cobra.OnlyValidArgs, cobra.MinimumNArgs(1)), Args: cobra.MatchAll(cobra.OnlyValidArgs, cobra.MinimumNArgs(1)),
@@ -114,7 +112,7 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
return err return err
} }
conf, hostConfig, err := dev.Parse(cmd.Flags(), options.ContainerOptions) conf, hostConfig, err := run.Parse(cmd.Flags(), options.ContainerOptions)
if err != nil { if err != nil {
return err return err
} }
@@ -137,15 +135,15 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
cmd.Flags().BoolVar(&options.NoProxy, "no-proxy", false, "Whether proxy remote workloads traffic into local or not, true: just startup container on local without inject containers to intercept traffic, false: intercept traffic and forward to local") cmd.Flags().BoolVar(&options.NoProxy, "no-proxy", false, "Whether proxy remote workloads traffic into local or not, true: just startup container on local without inject containers to intercept traffic, false: intercept traffic and forward to local")
cmdutil.AddContainerVarFlags(cmd, &options.ContainerName, options.ContainerName) cmdutil.AddContainerVarFlags(cmd, &options.ContainerName, options.ContainerName)
cmdutil.CheckErr(cmd.RegisterFlagCompletionFunc("container", completion.ContainerCompletionFunc(f))) cmdutil.CheckErr(cmd.RegisterFlagCompletionFunc("container", completion.ContainerCompletionFunc(f)))
cmd.Flags().StringVar((*string)(&options.ConnectMode), "connect-mode", string(dev.ConnectModeHost), "Connect to kubernetes network in container or in host, eg: ["+string(dev.ConnectModeContainer)+"|"+string(dev.ConnectModeHost)+"]") cmd.Flags().StringVar((*string)(&options.ConnectMode), "connect-mode", string(run.ConnectModeHost), "Connect to kubernetes network in container or in host, eg: ["+string(run.ConnectModeContainer)+"|"+string(run.ConnectModeHost)+"]")
handler.AddCommonFlags(cmd.Flags(), &transferImage, &imagePullSecretName) handler.AddCommonFlags(cmd.Flags(), &transferImage, &imagePullSecretName)
cmd.Flags().StringVar(&managerNamespace, "manager-namespace", "", "The namespace where the traffic manager is to be found. Only works in cluster mode (install kubevpn server by helm)") cmd.Flags().StringVar(&managerNamespace, "manager-namespace", "", "The namespace where the traffic manager is to be found. Only works in cluster mode (install kubevpn server by helm)")
// diy docker options // diy docker options
cmd.Flags().StringVar(&options.DevImage, "dev-image", "", "Use to startup docker container, Default is pod image") cmd.Flags().StringVar(&options.DevImage, "dev-image", "", "Use to startup docker container, Default is pod image")
// -- origin docker options -- start // -- origin docker options -- start
options.ContainerOptions = dev.AddFlags(cmd.Flags()) options.ContainerOptions = run.AddFlags(cmd.Flags())
cmd.Flags().StringVar(&options.RunOptions.Pull, "pull", dev.PullImageMissing, `Pull image before running ("`+dev.PullImageAlways+`"|"`+dev.PullImageMissing+`"|"`+dev.PullImageNever+`")`) cmd.Flags().StringVar(&options.RunOptions.Pull, "pull", run.PullImageMissing, `Pull image before running ("`+run.PullImageAlways+`"|"`+run.PullImageMissing+`"|"`+run.PullImageNever+`")`)
command.AddPlatformFlag(cmd.Flags(), &options.RunOptions.Platform) command.AddPlatformFlag(cmd.Flags(), &options.RunOptions.Platform)
// -- origin docker options -- end // -- origin docker options -- end
handler.AddExtraRoute(cmd.Flags(), &options.ExtraRouteInfo) handler.AddExtraRoute(cmd.Flags(), &options.ExtraRouteInfo)

View File

@@ -2,6 +2,7 @@ package cmds
import ( import (
"context" "context"
"fmt"
"os" "os"
pkgerr "github.com/pkg/errors" pkgerr "github.com/pkg/errors"
@@ -57,12 +58,12 @@ func CmdSync(f cmdutil.Factory) *cobra.Command {
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │ │ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘ └──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
kubevpn sync service/productpage --ssh-alias <alias> --headers foo=bar kubevpn sync deployment/productpage --ssh-alias <alias> --headers foo=bar
# Support ssh auth GSSAPI # Support ssh auth GSSAPI
kubevpn sync service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab kubevpn sync deployment/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab
kubevpn sync service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache kubevpn sync deployment/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache
kubevpn sync service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD> kubevpn sync deployment/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD>
`)), `)),
Args: cobra.MatchAll(cobra.OnlyValidArgs, cobra.MinimumNArgs(1)), Args: cobra.MatchAll(cobra.OnlyValidArgs, cobra.MinimumNArgs(1)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) { PreRunE: func(cmd *cobra.Command, args []string) (err error) {
@@ -134,7 +135,7 @@ func CmdSync(f cmdutil.Factory) *cobra.Command {
} }
return err return err
} }
util.Print(os.Stdout, config.Slogan) _, _ = fmt.Fprintln(os.Stdout, config.Slogan)
return nil return nil
}, },
} }

View File

@@ -46,15 +46,18 @@ func LocalTCPForwarder(ctx context.Context, s *stack.Stack) func(stack.Transport
// 2, dial proxy // 2, dial proxy
var host string var host string
var network string
if id.LocalAddress.To4() != (tcpip.Address{}) { if id.LocalAddress.To4() != (tcpip.Address{}) {
host = "127.0.0.1" host = "127.0.0.1"
network = "tcp4"
} else { } else {
host = net.IPv6loopback.String() host = net.IPv6loopback.String()
network = "tcp6"
} }
port := fmt.Sprintf("%d", id.LocalPort) port := fmt.Sprintf("%d", id.LocalPort)
var d = net.Dialer{Timeout: time.Second * 5} var d = net.Dialer{Timeout: time.Second * 5}
var remote net.Conn var remote net.Conn
remote, err = d.DialContext(ctx, "tcp", net.JoinHostPort(host, port)) remote, err = d.DialContext(ctx, network, net.JoinHostPort(host, port))
if err != nil { if err != nil {
plog.G(ctx).Errorf("[TUN-TCP] Failed to connect addr %s: %v", net.JoinHostPort(host, port), err) plog.G(ctx).Errorf("[TUN-TCP] Failed to connect addr %s: %v", net.JoinHostPort(host, port), err)
return return

View File

@@ -13,7 +13,7 @@ import (
"github.com/wencaiwulue/kubevpn/v2/pkg/util" "github.com/wencaiwulue/kubevpn/v2/pkg/util"
) )
type gvisorLocalTCPHandler struct { type gvisorLocalHandler struct {
// read from tcp conn write to gvisor inbound // read from tcp conn write to gvisor inbound
gvisorInbound <-chan *Packet gvisorInbound <-chan *Packet
// write to tcp conn // write to tcp conn
@@ -23,15 +23,15 @@ type gvisorLocalTCPHandler struct {
errChan chan error errChan chan error
} }
func handleGvisorPacket(gvisorInbound <-chan *Packet, outbound chan<- *Packet) *gvisorLocalTCPHandler { func handleGvisorPacket(gvisorInbound <-chan *Packet, outbound chan<- *Packet) *gvisorLocalHandler {
return &gvisorLocalTCPHandler{ return &gvisorLocalHandler{
gvisorInbound: gvisorInbound, gvisorInbound: gvisorInbound,
outbound: outbound, outbound: outbound,
errChan: make(chan error, 1), errChan: make(chan error, 1),
} }
} }
func (h *gvisorLocalTCPHandler) Run(ctx context.Context) { func (h *gvisorLocalHandler) Run(ctx context.Context) {
endpoint := channel.New(tcp.DefaultReceiveBufferSize, uint32(config.DefaultMTU), tcpip.GetRandMacAddr()) endpoint := channel.New(tcp.DefaultReceiveBufferSize, uint32(config.DefaultMTU), tcpip.GetRandMacAddr())
// for support ipv6 skip checksum // for support ipv6 skip checksum
// vendor/gvisor.dev/gvisor/pkg/tcpip/stack/nic.go:763 // vendor/gvisor.dev/gvisor/pkg/tcpip/stack/nic.go:763

View File

@@ -88,6 +88,6 @@ func readFromGvisorInboundWriteToEndpoint(ctx context.Context, in <-chan *Packet
sniffer.LogPacket("[gVISOR] ", sniffer.DirectionRecv, protocol, pkt) sniffer.LogPacket("[gVISOR] ", sniffer.DirectionRecv, protocol, pkt)
endpoint.InjectInbound(protocol, pkt) endpoint.InjectInbound(protocol, pkt)
pkt.DecRef() pkt.DecRef()
plog.G(ctx).Debugf("[TCP-GVISOR] Write to Gvisor. SRC: %s, DST: %s, Protocol: %s, Length: %d", src, dst, ipProto.String(), packet.length) plog.G(ctx).Debugf("[TCP-GVISOR] Write to gvisor. SRC: %s, DST: %s, IPProtocol: %s, Protocol: %v, Length: %d", src, dst, ipProto.String(), protocol, packet.length)
} }
} }

View File

@@ -29,10 +29,13 @@ func LocalUDPForwarder(ctx context.Context, s *stack.Stack) func(id stack.Transp
Port: int(id.RemotePort), Port: int(id.RemotePort),
} }
var ip net.IP var ip net.IP
var network string
if id.LocalAddress.To4() != (tcpip.Address{}) { if id.LocalAddress.To4() != (tcpip.Address{}) {
ip = net.ParseIP("127.0.0.1") ip = net.ParseIP("127.0.0.1")
network = "udp4"
} else { } else {
ip = net.IPv6loopback ip = net.IPv6loopback
network = "udp6"
} }
dst := &net.UDPAddr{ dst := &net.UDPAddr{
IP: ip, IP: ip,
@@ -47,7 +50,7 @@ func LocalUDPForwarder(ctx context.Context, s *stack.Stack) func(id stack.Transp
} }
// dial dst // dial dst
remote, err1 := net.DialUDP("udp", nil, dst) remote, err1 := net.DialUDP(network, nil, dst)
if err1 != nil { if err1 != nil {
plog.G(ctx).Errorf("[TUN-UDP] Failed to connect dst: %s: %v", dst.String(), err1) plog.G(ctx).Errorf("[TUN-UDP] Failed to connect dst: %s: %v", dst.String(), err1)
return return

View File

@@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet" "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/stack" "gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
@@ -42,10 +43,16 @@ func TCPForwarder(ctx context.Context, s *stack.Stack) func(stack.TransportEndpo
}() }()
// 2, dial proxy // 2, dial proxy
host := id.LocalAddress.String() host := id.LocalAddress.String()
var network string
if id.LocalAddress.To4() != (tcpip.Address{}) {
network = "tcp4"
} else {
network = "tcp6"
}
port := fmt.Sprintf("%d", id.LocalPort) port := fmt.Sprintf("%d", id.LocalPort)
var remote net.Conn var remote net.Conn
var d = net.Dialer{Timeout: time.Second * 5} var d = net.Dialer{Timeout: time.Second * 5}
remote, err = d.DialContext(ctx, "tcp", net.JoinHostPort(host, port)) remote, err = d.DialContext(ctx, network, net.JoinHostPort(host, port))
if err != nil { if err != nil {
plog.G(ctx).Errorf("[TUN-TCP] Failed to connect addr %s: %v", net.JoinHostPort(host, port), err) plog.G(ctx).Errorf("[TUN-TCP] Failed to connect addr %s: %v", net.JoinHostPort(host, port), err)
return return

View File

@@ -112,7 +112,7 @@ func (h *gvisorTCPHandler) readFromTCPConnWriteToEndpoint(ctx context.Context, c
sniffer.LogPacket("[gVISOR] ", sniffer.DirectionRecv, protocol, pkt) sniffer.LogPacket("[gVISOR] ", sniffer.DirectionRecv, protocol, pkt)
endpoint.InjectInbound(protocol, pkt) endpoint.InjectInbound(protocol, pkt)
pkt.DecRef() pkt.DecRef()
plog.G(ctx).Debugf("[TCP-GVISOR] Write to Gvisor. SRC: %s, DST: %s, Protocol: %s, Length: %d", src, dst, layers.IPProtocol(ipProtocol).String(), read) plog.G(ctx).Debugf("[TCP-GVISOR] Write to gvisor. SRC: %s, DST: %s, Protocol: %s, Length: %d", src, dst, layers.IPProtocol(ipProtocol).String(), read)
} else { } else {
util.SafeWrite(TCPPacketChan, &Packet{ util.SafeWrite(TCPPacketChan, &Packet{
data: buf[:], data: buf[:],

View File

@@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet" "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/stack" "gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/udp" "gvisor.dev/gvisor/pkg/tcpip/transport/udp"
@@ -39,8 +40,15 @@ func UDPForwarder(ctx context.Context, s *stack.Stack) func(id stack.TransportEn
return return
} }
var network string
if id.LocalAddress.To4() != (tcpip.Address{}) {
network = "udp4"
} else {
network = "udp6"
}
// dial dst // dial dst
remote, err1 := net.DialUDP("udp", nil, dst) remote, err1 := net.DialUDP(network, nil, dst)
if err1 != nil { if err1 != nil {
plog.G(ctx).Errorf("[TUN-UDP] Failed to connect dst: %s: %v", dst.String(), err1) plog.G(ctx).Errorf("[TUN-UDP] Failed to connect dst: %s: %v", dst.String(), err1)
return return

View File

@@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
"gvisor.dev/gvisor/pkg/tcpip"
"github.com/wencaiwulue/kubevpn/v2/pkg/config" "github.com/wencaiwulue/kubevpn/v2/pkg/config"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log" plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
@@ -24,21 +25,27 @@ func (h *gvisorUDPHandler) Handle(ctx context.Context, tcpConn net.Conn) {
defer tcpConn.Close() defer tcpConn.Close()
plog.G(ctx).Debugf("[TUN-UDP] %s -> %s", tcpConn.RemoteAddr(), tcpConn.LocalAddr()) plog.G(ctx).Debugf("[TUN-UDP] %s -> %s", tcpConn.RemoteAddr(), tcpConn.LocalAddr())
// 1, get proxy info // 1, get proxy info
endpointID, err := util.ParseProxyInfo(tcpConn) id, err := util.ParseProxyInfo(tcpConn)
if err != nil { if err != nil {
plog.G(ctx).Errorf("[TUN-UDP] Failed to parse proxy info: %v", err) plog.G(ctx).Errorf("[TUN-UDP] Failed to parse proxy info: %v", err)
return return
} }
plog.G(ctx).Infof("[TUN-UDP] LocalPort: %d, LocalAddress: %s, RemotePort: %d, RemoteAddress: %s", plog.G(ctx).Infof("[TUN-UDP] LocalPort: %d, LocalAddress: %s, RemotePort: %d, RemoteAddress: %s",
endpointID.LocalPort, endpointID.LocalAddress.String(), endpointID.RemotePort, endpointID.RemoteAddress.String(), id.LocalPort, id.LocalAddress.String(), id.RemotePort, id.RemoteAddress.String(),
) )
// 2, dial proxy // 2, dial proxy
addr := &net.UDPAddr{ addr := &net.UDPAddr{
IP: endpointID.LocalAddress.AsSlice(), IP: id.LocalAddress.AsSlice(),
Port: int(endpointID.LocalPort), Port: int(id.LocalPort),
}
var network string
if id.LocalAddress.To4() != (tcpip.Address{}) {
network = "udp4"
} else {
network = "udp6"
} }
var remote *net.UDPConn var remote *net.UDPConn
remote, err = net.DialUDP("udp", nil, addr) remote, err = net.DialUDP(network, nil, addr)
if err != nil { if err != nil {
plog.G(ctx).Errorf("[TUN-UDP] Failed to connect addr %s: %v", addr.String(), err) plog.G(ctx).Errorf("[TUN-UDP] Failed to connect addr %s: %v", addr.String(), err)
return return

View File

@@ -1,4 +1,4 @@
package dev package run
import ( import (
"fmt" "fmt"

View File

@@ -1,4 +1,4 @@
package dev package run
import ( import (
"strings" "strings"

View File

@@ -1,4 +1,4 @@
package dev package run
import ( import (
"context" "context"
@@ -84,7 +84,7 @@ func (option *Options) Main(ctx context.Context, sshConfig *pkgssh.SshConfig, co
return err return err
} }
return option.Dev(ctx, config, hostConfig) return option.Run(ctx, config, hostConfig)
} }
// Connect to cluster network on docker container or host // Connect to cluster network on docker container or host
@@ -103,7 +103,7 @@ func (option *Options) Connect(ctx context.Context, sshConfig *pkgssh.SshConfig,
option.ExtraRouteInfo.ExtraCIDR = append(option.ExtraRouteInfo.ExtraCIDR, ip.String()) option.ExtraRouteInfo.ExtraCIDR = append(option.ExtraRouteInfo.ExtraCIDR, ip.String())
} }
} }
// not needs to ssh jump in daemon, because dev mode will hang up until user exit, // no need to ssh jump in daemon, because run mode will hang up until user exit,
// so just ssh jump in client is enough // so just ssh jump in client is enough
req := &rpc.ProxyRequest{ req := &rpc.ProxyRequest{
KubeconfigBytes: string(kubeConfigBytes), KubeconfigBytes: string(kubeConfigBytes),
@@ -181,7 +181,7 @@ func (option *Options) Connect(ctx context.Context, sshConfig *pkgssh.SshConfig,
return fmt.Errorf("unsupport connect mode: %s", option.ConnectMode) return fmt.Errorf("unsupport connect mode: %s", option.ConnectMode)
} }
func (option *Options) Dev(ctx context.Context, config *Config, hostConfig *HostConfig) error { func (option *Options) Run(ctx context.Context, config *Config, hostConfig *HostConfig) error {
templateSpec, err := option.GetPodTemplateSpec(ctx) templateSpec, err := option.GetPodTemplateSpec(ctx)
if err != nil { if err != nil {
plog.G(ctx).Errorf("Failed to get unstructured object error: %v", err) plog.G(ctx).Errorf("Failed to get unstructured object error: %v", err)

View File

@@ -1,4 +1,4 @@
package dev package run
import ( import (
"context" "context"

View File

@@ -113,13 +113,11 @@ func GetPodTemplateSpecPath(u *unstructured.Unstructured) (*v1.PodTemplateSpec,
NormalizedResource convert user parameter to standard, example: NormalizedResource convert user parameter to standard, example:
pod/productpage-7667dfcddb-cbsn5 --> deployments.apps/productpage pod/productpage-7667dfcddb-cbsn5 --> deployments.apps/productpage
service/productpage --> deployments.apps/productpage
replicaset/productpage-7667dfcddb --> deployments.apps/productpage replicaset/productpage-7667dfcddb --> deployments.apps/productpage
deployment: productpage --> deployments.apps/productpage deployment: productpage --> deployments.apps/productpage
pods without controller pods without controller
pod/productpage-without-controller --> pod/productpage-without-controller pod/productpage-without-controller --> pod/productpage-without-controller
service/productpage-without-pod --> controller/controllerName
*/ */
func NormalizedResource(f util.Factory, ns string, workloads []string) ([]string, []*resource.Info, error) { func NormalizedResource(f util.Factory, ns string, workloads []string) ([]string, []*resource.Info, error) {
if len(workloads) == 0 { if len(workloads) == 0 {