Skip to content

Commit

Permalink
improvement: kubefile
Browse files Browse the repository at this point in the history
  • Loading branch information
shaowenchen committed Jul 22, 2024
1 parent 52dfeb1 commit 8fcc541
Show file tree
Hide file tree
Showing 17 changed files with 263 additions and 102 deletions.
12 changes: 6 additions & 6 deletions cmd/cli/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (

var hostOpt option.HostOption
var fileOpt option.FileOption
var kubeOpt option.KubeOption
var inventory string
var verbose string

Expand All @@ -32,7 +31,7 @@ var FileCmd = &cobra.Command{
if inventoryType == constants.InventoryTypeHosts {
HostFile(ctx, logger, fileOpt, hostOpt, inventory)
} else if inventoryType == constants.InventoryTypeKubernetes {
KubeFile(ctx, logger, fileOpt, kubeOpt, inventory)
KubeFile(ctx, logger, fileOpt, inventory)
}
},
}
Expand All @@ -51,13 +50,13 @@ func HostFile(ctx context.Context, logger *log.Logger, fileOpt option.FileOption
return
}

func KubeFile(ctx context.Context, logger *log.Logger, fileOpt option.FileOption, kubeOpt option.KubeOption, inventory string) (err error) {
func KubeFile(ctx context.Context, logger *log.Logger, fileOpt option.FileOption, inventory string) (err error) {
client, err := utils.NewKubernetesClient(inventory)
if err != nil {
logger.Error.Println(err)
return
}
nodeList, err := kube.GetNodes(ctx, logger, client, kubeOpt)
nodeList, err := kube.GetNodes(ctx, logger, client, fileOpt.KubeOption)
if err != nil {
logger.Error.Println(err)
}
Expand Down Expand Up @@ -93,6 +92,7 @@ func init() {
FileCmd.Flags().StringVarP(&hostOpt.PrivateKeyPath, "privatekeypath", "", constants.GetCurrentUserPrivateKeyPath(), "")
FileCmd.Flags().IntVar(&hostOpt.Port, "port", 22, "")

FileCmd.Flags().StringVarP(&kubeOpt.NodeName, "nodename", "", "", "")
FileCmd.Flags().StringVarP(&kubeOpt.OpsNamespace, "opsnamespace", "", constants.DefaultOpsNamespace, "ops work namespace")
FileCmd.Flags().StringVarP(&fileOpt.NodeName, "nodename", "", "", "")
FileCmd.Flags().StringVarP(&fileOpt.RuntimeImage, "runtimeimage", "", constants.OpsCliRuntimeImage, "")
FileCmd.Flags().StringVarP(&fileOpt.OpsNamespace, "opsnamespace", "", constants.DefaultOpsNamespace, "ops work namespace")
}
87 changes: 37 additions & 50 deletions docs/content/opscli-file.md
Original file line number Diff line number Diff line change
@@ -1,99 +1,86 @@
## opscli file command

### `-i` 指定操作目标清单
### 主机 - 本地与对象存储互传文件

- 指定主机

`-i 1.1.1.1`

通过 `--username` 指定用户名,`--password` 指定密码。
- 设置 AK\SK

- 批量主机
```bash
export ak=
export sk=
```

`-i hosts.txt`
- 上传本地文件 `./tmp.log` 到对象存储 `s3://logs/tmp.log`

```bash
cat hosts.txt

1.1.1.1
2.2.2.2
/usr/local/bin/opscli file --direction upload --localfile ./tmp.log --remotefile s3://logs/tmp.log --bucket obs-test
```

opscli 会从每行中正则匹配 ip 地址,作为目标地址
`--bucket` 为 S3 bucket 名称,`--region` 为 S3 bucket 所在区域,`--endpoint` 为 S3 bucket 的 endpoint,`--direction` 为上传方向,`--localfile` 为本地文件,`--remotefile` 为远程文件

- 集群全部节点
- 下载 S3 `s3://logs/tmp.log` 到本地文件 `./tmp1.log`

```bash
-i ~/.kube/config --all
/usr/local/bin/opscli file --direction download --localfile ./tmp1.log --remotefile s3://logs/tmp.log --bucket obs-test
```

`-i` 默认值为 `~/.kube/config`

- 集群指定节点
- 清理 AK\SK

```bash
-i ~/.kube/config --nodename node1
unset ak
unset sk
```

node1 为节点名称。
### 主机 - 本地与 API Server 互传文件

### 本地文件与对象存储文件互传
> 提供本地加解密,与服务器端进行文件传输
- 设置 AK\SK
- 上传

```bash
export ak=
export sk=
/usr/local/bin/opscli file --direction upload --api https://uploadapi.vinqi.com/api/v1/files --aeskey "" --localfile ./tmp.log

Please use the following command to download the file:
opscli file --api https://uploadapi.vinqi.com/api/v1/files --aeskey xxx --direction download --remotefile https://download_url_link.com.aes
```

- 上传本地文件 `./tmp.log` 到对象存储 `s3://logs/tmp.log`
这里的 api 提供上传服务,aeskey 为空字符串时自动生成一个随机秘钥,如果不设置 aeskey 默认为 unset 将不会进行文件加密。

- 下载

```bash
/usr/local/bin/opscli file --direction upload --localfile ./tmp.log --remotefile s3://logs/tmp.log --bucket obs-test
/usr/local/bin/opscli file --api https://uploadapi.vinqi.com/api/v1/files --aeskey xxx --direction download --remotefile https://download_url_link.com.aes
```

`--bucket` 为 S3 bucket 名称,`--region` 为 S3 bucket 所在区域,`--endpoint` 为 S3 bucket 的 endpoint,`--direction` 为上传方向,`--localfile` 为本地文件,`--remotefile` 为远程文件。
### 集群 - 本地与 API Server 互传文件

- 下载 S3 `s3://logs/tmp.log` 到本地文件 `./tmp1.log`
- 上传

```bash
/usr/local/bin/opscli file --direction download --localfile ./tmp1.log --remotefile s3://logs/tmp.log --bucket obs-test
/usr/local/bin/opscli file -i ~/.kube/config --nodename node1 --direction upload --api https://uploadapi.vinqi.com/api/v1/files --aeskey "" --localfile /root/tmp.log --runtimeimage shaowenchen/ops-cli
```

- 清理 AK\SK
- 下载

```bash
unset ak
unset sk
/usr/local/bin/opscli file -i ~/.kube/config --nodename xxx --direction download --api https://uploadapi.vinqi.com/api/v1/files --aeskey xxx --localfile /root/tmp1.log --remotefile https://uploadapi.vinqi.com/uploadbases/cdn0/raw/1721621949-tmp.log.aes --runtimeimage shaowenchen/ops-cli
```

### 本地文件分发到远程主机上
### 集群 - 本地与对象存储互传文件

- 上传本地文件 `./tmp.log` 到远程主机 `/tmp/tmp.log`
- 上传

```bash
/usr/local/bin/opscli file --direction upload --localfile ./tmp.log --remotefile /tmp/tmp.log -i 1.2.3.4 --port 2222 --username root
/usr/local/bin/opscli file -i ~/.kube/config --nodename xxx --direction upload --ak xxx --sk xxx --region beijing --endpoint ks3-cn-beijing.ksyun.com --bucket multimodal --localfile /root/tmp.log --remotefile s3://logs/tmp.log --runtimeimage shaowenchen/ops-cli
```

- 下载远程主机 `/tmp/tmp.log` 到本地文件 `./tmp1.log`
- 下载

```bash
/usr/local/bin/opscli file --direction download --localfile ./tmp1.log --remotefile /tmp/tmp.log -i 1.2.3.4 --port 2222 --username root
/usr/local/bin/opscli file -i ~/.kube/config --nodename xxx --direction download --ak xxx --sk xxx --region beijing --endpoint ks3-cn-beijing.ksyun.com --bucket multimodal --localfile /root/tmp2.log --remotefile s3://logs/tmp.log --runtimeimage shaowenchen/ops-cli
```

### 本地文件上传到 API Server,可加密

> 提供本地加解密,与服务器端进行文件传输
- 上传本地文件 `./tmp.log` 到 API Server
### 集群 - 镜像文件拷贝到本地

```bash
/usr/local/bin/opscli file --direction upload --api https://uploadapi.vinqi.com/api/v1/files --aeskey "" --localfile ./tmp.log

Please use the following command to download the file:
opscli file --api https://uploadapi.vinqi.com/api/v1/files --aeskey xxxxxxxxxxx --direction download --remotefile https://download_url_link.com.aes
/usr/local/bin/opscli file -i ~/.kube/config --nodename xxx --direction download --localfile /root/opscli-copy --remotefile shaowenchen/ops-cli:latest:///usr/local/bin/opscli
```

这里的 api 提供上传服务,aeskey 为空字符串时自动生成一个随机秘钥,如果不设置 aeskey 默认为 unset 将不会进行文件加密。

### 从镜像中提取文件到集群主机
43 changes: 42 additions & 1 deletion docs/content/opscli-task.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,45 @@ node1 为节点名称。

```bash
/usr/local/bin/opscli task -f ~/.ops/tasks/app-istio.yaml --version 1.13.7 --kubeconfig /etc/kubernetes/admin.conf --action delete
```
```

### 上传文件

- 上传到 Server

```bash
/usr/local/bin/opscli task -f tasks/file-upload.yaml --api https://uploadapi.vinqi.com/api/v1/files --localfile dockerfile

> Run Task ops-system/file-upload on 127.0.0.1
(1/1) upload file
Please use the following command to download the file:
opscli file --api https://uploadapi.vinqi.com/api/v1/files --aeskey a9f891afe71fda777b05a7063068360a914e83848d7da46d7513aee86c053f6c --direction download --remotefile https://uploadapi.vinqi.com/uploadbases/cdn0/raw/1721615659-dockerfile.aes
```

- 上传到 S3

```bash
/usr/local/bin/opscli task -f tasks/file-upload.yaml --ak xxx --sk xxx --region beijing --endpoint ks3-cn-beijing.ksyun.com --bucket xxx --localfile dockerfile --remotefile s3://dockerfile
```

### 下载文件

- 从 Server 下载

```bash
/usr/local/bin/opscli task -f task -f tasks/file-download.yaml --api https://uploadapi.vinqi.com/api/v1/files --aeskey a9f891afe71fda777b05a7063068360a914e83848d7da46d7513aee86c053f6c --remotefile https://uploadapi.vinqi.com/uploadbases/cdn0/raw/1721615659-dockerfile.aes --localfile dockerfile1

> Run Task ops-system/file-download on 127.0.0.1
(1/1) download file
success download https://uploadapi.vinqi.com/uploadbases/cdn0/raw/1721615659-dockerfile.aes to dockerfile1
```

- 从 S3 下载

```bash
/usr/local/bin/opscli task -f tasks/file-download.yaml --ak xxx --sk xxx --region beijing --endpoint ks3-cn-beijing.ksyun.com --bucket xxx --localfile dockerfile2 --remotefile s3://dockerfile

> Run Task ops-system/file-download on 127.0.0.1
(1/1) download file
success download s3 dockerfile to dockerfile2
```
1 change: 1 addition & 0 deletions pkg/constants/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const LabelOpsTaskValue = "task"
const KubeAdminConfigPath = "/etc/kubernetes/admin.conf"

const DefaultRuntimeImage = "docker.io/library/ubuntu:20.04"
const OpsCliRuntimeImage = "shaowenchen/opscli"

const SyncResourceStatusHeatSeconds = 60 * 5
const SyncResourceRandomBiasSeconds = 60 * 2
Expand Down
2 changes: 1 addition & 1 deletion pkg/kube/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ func (kc *KubeConnection) FileNode(logger *opslog.Logger, node *corev1.Node, fil
pod := &corev1.Pod{}
if fileOpt.GetStorageType() == constants.RemoteStorageTypeS3 {
if fileOpt.IsUploadDirection() {
pod, err = UploadS3FileOnNode(kc.Client, node, namespacedName, fileOpt)
pod, err = RunFileOnNode(kc.Client, node, namespacedName, fileOpt)
if err != nil {
return
}
Expand Down
16 changes: 6 additions & 10 deletions pkg/kube/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,13 @@ func File(logger *log.Logger, client *kubernetes.Clientset, node v1.Node, fileOp
if err != nil {
logger.Error.Println(err)
}
if fileOpt.GetStorageType() == constants.RemoteStorageTypeS3 {
if fileOpt.IsUploadDirection() {
pod, err := UploadS3FileOnNode(client, &node, namespacedName, fileOpt)
if err != nil {
logger.Error.Println(err)
}
stdout, err = GetPodLog(logger, context.TODO(), false, client, pod)
logger.Info.Println(stdout)
}
pod := &v1.Pod{}
pod, err = RunFileOnNode(client, &node, namespacedName, fileOpt)
if err != nil {
logger.Error.Println(err)
}

stdout, err = GetPodLog(logger, context.TODO(), false, client, pod)
logger.Info.Println(stdout)
return
}

Expand Down
47 changes: 37 additions & 10 deletions pkg/kube/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package kube

import (
"context"
"errors"
"fmt"
"strings"

"github.com/shaowenchen/ops/pkg/constants"
"github.com/shaowenchen/ops/pkg/option"
"github.com/shaowenchen/ops/pkg/utils"
Expand All @@ -11,7 +14,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"strings"
)

func RunShellOnNode(client *kubernetes.Clientset, node *v1.Node, namespacedName types.NamespacedName, image string, shell string) (pod *corev1.Pod, err error) {
Expand Down Expand Up @@ -96,7 +98,34 @@ func RunShellOnNode(client *kubernetes.Clientset, node *v1.Node, namespacedName
return
}

func UploadS3FileOnNode(client *kubernetes.Clientset, node *v1.Node, namespacedName types.NamespacedName, fileOpt option.FileOption) (pod *corev1.Pod, err error) {
func RunFileOnNode(client *kubernetes.Clientset, node *v1.Node, namespacedName types.NamespacedName, fileOpt option.FileOption) (pod *corev1.Pod, err error) {
hostLocalfile := "/host" + fileOpt.LocalFile
cmd := ""
switch fileOpt.GetStorageType() {
case constants.RemoteStorageTypeS3:
if fileOpt.IsDownloadDirection() {
cmd = utils.ShellOpscliDownS3(fileOpt.Region, fileOpt.Endpoint, fileOpt.Bucket,
fileOpt.AK, fileOpt.SK, hostLocalfile, fileOpt.RemoteFile)
} else if fileOpt.IsUploadDirection() {
cmd = utils.ShellOpscliUploadS3(fileOpt.Region, fileOpt.Endpoint, fileOpt.Bucket,
fileOpt.AK, fileOpt.SK, hostLocalfile, fileOpt.RemoteFile)
}
case constants.RemoteStorageTypeServer:
if fileOpt.IsDownloadDirection() {
cmd = utils.ShellOpscliDownServer(fileOpt.Api, fileOpt.AesKey, hostLocalfile, fileOpt.RemoteFile)
} else if fileOpt.IsUploadDirection() {
cmd = utils.ShellOpscliUploadServer(fileOpt.Api, fileOpt.AesKey, hostLocalfile, fileOpt.RemoteFile)
}
case constants.RemoteStorageTypeImage:
if fileOpt.IsDownloadDirection() {
cmd = fmt.Sprintf("cp -rbf %s %s", fileOpt.RemoteFile, hostLocalfile)
}
}
if cmd == "" {
err = errors.New("empty cmd")
return
}

tolerations := []v1.Toleration{}
for _, taint := range node.Spec.Taints {
tolerations = append(tolerations, v1.Toleration{
Expand All @@ -122,13 +151,11 @@ func UploadS3FileOnNode(client *kubernetes.Clientset, node *v1.Node, namespacedN
NodeName: node.Name,
Containers: []corev1.Container{
{
Name: "file",
Image: fileOpt.RuntimeImage,
Command: []string{"bash"},
Args: []string{"-c", fmt.Sprintf("opscli file --direction upload"+
" --endpoint %s --ak %s --sk %s --region %s --bucket %s --localfile /host%s --remotefile s3://%s",
fileOpt.Endpoint, fileOpt.AK, fileOpt.SK, fileOpt.Region, fileOpt.Bucket, fileOpt.LocalFile, fileOpt.Endpoint)},
ImagePullPolicy: corev1.PullAlways,
Name: "file",
Image: fileOpt.RuntimeImage,
Command: []string{"bash"},
Args: []string{"-c", cmd},
ImagePullPolicy: corev1.PullIfNotPresent,
VolumeMounts: []v1.VolumeMount{
{
Name: "data",
Expand Down Expand Up @@ -188,7 +215,7 @@ func DownloadS3FileOnNode(client *kubernetes.Clientset, node *v1.Node, namespace
Args: []string{"-c", fmt.Sprintf("opscli file --direction upload"+
" --endpoint %s --ak %s --sk %s --region %s --bucket %s --localfile /host%s --remotefile s3://%s",
fileOpt.Endpoint, fileOpt.AK, fileOpt.SK, fileOpt.Region, fileOpt.Bucket, fileOpt.LocalFile, fileOpt.LocalFile)},
ImagePullPolicy: corev1.PullAlways,
ImagePullPolicy: corev1.PullIfNotPresent,
VolumeMounts: []v1.VolumeMount{
{
Name: "data",
Expand Down
1 change: 1 addition & 0 deletions pkg/option/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ func (f *FileOption) GetStorageType() string {
f.RemoteFile = remoteSplit[1]
} else {
f.StorageType = constants.RemoteStorageTypeImage
f.RuntimeImage = remoteSplit[0]
f.RemoteFile = remoteSplit[1]
}
return f.StorageType
Expand Down
1 change: 0 additions & 1 deletion pkg/storage/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ func decrypt(ciphertext []byte, key []byte) ([]byte, error) {
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]

// 使用AES加密算法中的CTR模式
stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(ciphertext, ciphertext)

Expand Down
Loading

0 comments on commit 8fcc541

Please sign in to comment.