Skip to content

Commit

Permalink
feat: 新增 container agent && 更新文档
Browse files Browse the repository at this point in the history
  • Loading branch information
googs1025 committed Jan 6, 2024
1 parent b4752a5 commit b84c76f
Show file tree
Hide file tree
Showing 28 changed files with 430 additions and 105 deletions.
1 change: 0 additions & 1 deletion 1.txt

This file was deleted.

32 changes: 32 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Build the manager binary
FROM golang:1.18.7-alpine3.15 as builder

WORKDIR /app
# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
# 坑:
# 报错 go mod download: google.golang.org/[email protected]: read tcp 172.17.0.3:60862->14.204.51.154:443: read: connection reset by peer
# The command '/bin/sh -c go mod download' returned a non-zero code: 1
# make: *** [docker-build] 错误 1
ENV GOPROXY=https://goproxy.cn,direct
ENV GO111MODULE=on
# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go mod download

# Copy the go source
# # 需要把该放入的都copy进去,如果报出 package xxxxx is not in GOROOT => 就是这个问题。
COPY main.go main.go
COPY pkg/ pkg/
# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o taskflowoperator main.go


FROM alpine:3.12
WORKDIR /app
# 需要的文件需要复制过来
COPY --from=builder /app/taskflowoperator .
USER 65532:65532

ENTRYPOINT ["./taskflowoperator"]
137 changes: 133 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,136 @@
## task-operator 简易型工作流控制器
## taskflow-operator 简易型任务流控制器

### 项目思路与设计
![]()
设计背景:
设计背景:k8s 当中原生的 Pod 资源对象执行 container 容器时,并没有相互依赖的编排特性(ex: 容器 a 完成后 -> 再执行容器 b ...)。
本项目在此需求上,基于 k8s 的扩展功能,实现 Task 的自定义资源控制器,实现一个能顺序执行容器的 operator 应用

思路:
```yaml
apiVersion: api.practice.com/v1alpha1
kind: Task
metadata:
name: example-taskflow
spec:
# 设置多个 step 步骤,会按照填入的 container 顺序执行
steps:
# 每项都是一个 container 对象
- name: step1
image: busybox:1.28
command: [ "sh","-c" ]
args: [ "echo step1" ]
- name: step2
image: busybox:1.28
command: [ "sh","-c" ]
args: [ "echo step2" ]
- name: step3
image: devopscube/kubernetes-job-demo:latest
args: [ "100" ]
```
### 项目功能
1. 支持任务中的 container 顺序执行
### 项目部署与使用
1. 打成镜像或是使用编译二进制。
```bash
# 项目根目录执行
[root@VM-0-16-centos taskflowoperator]# pwd
/root/taskflowoperator
# 下列命令会得到一个二进制文件,服务启动时需要使用。
# 可以直接使用 docker 镜像部署
[root@VM-0-16-centos taskflowoperator]# docker build -t taskflowoperator:v1 .
Sending build context to Docker daemon 194.6kB
Step 1/15 : FROM golang:1.18.7-alpine3.15 as builder
---> 33c97f935029
Step 2/15 : WORKDIR /app
...
```
2. 构建 container agent 镜像
```bash
[root@VM-0-16-centos taskflowoperator]# chmod +x docker_build.sh
[root@VM-0-16-centos taskflowoperator]# ./docker_build.sh
镜像 docker.io/taskflow/agent:v1.0 不存在,开始构建...
Sending build context to Docker daemon 16.38kB
Step 1/17 : FROM golang:1.18.7-alpine3.15 as builder
---> 33c97f935029
Step 2/17 : RUN #mkdir /src
---> Using cache
---> abd15a740ce7
Step 3/17 : WORKDIR /app
---> Using cache
---> b25bc39a9a40
Step 4/17 : COPY go.mod go.mod
---> 6576edb8ae05
Step 5/17 : COPY go.sum go.sum
---> 3e30c14b75a4
Step 6/17 : ENV GOPROXY=https://goproxy.cn,direct
---> Running in d98da0a5296e
Removing intermediate container d98da0a5296e
---> a6263b47b54d
Step 7/17 : ENV GO111MODULE=on
---> Running in a6da28b7982d
Removing intermediate container a6da28b7982d
---> 613ebff35ca3
Step 8/17 : RUN go mod download
---> Running in 3b8e3931b18b
```

3. apply crd 资源
```bash
[root@VM-0-16-centos taskflowoperator]#
[root@VM-0-16-centos taskflowoperator]# kubectl apply -f deploy/task.yaml
customresourcedefinition.apiextensions.k8s.io/tasks.api.practice.com unchanged
```
4. 启动 controller 服务(需要先执行 rbac.yaml,否则服务会报错)
```bash
[root@VM-0-16-centos taskflowoperator]# kubectl apply -f deploy/task.yaml
customresourcedefinition.apiextensions.k8s.io/tasks.api.practice.com unchanged
[root@VM-0-16-centos taskflowoperator]# kubectl apply -f deploy/rbac.yaml
serviceaccount/taskflow-sa unchanged
clusterrole.rbac.authorization.k8s.io/taskflow-clusterrole unchanged
clusterrolebinding.rbac.authorization.k8s.io/taskflow-ClusterRoleBinding unchanged
[root@VM-0-16-centos taskflowoperator]# kubectl apply -f deploy/deploy.yaml
deployment.apps/taskflow-controller unchanged
```
5. 查看 operator 服务
```bash
[root@VM-0-16-centos deploy]# kubectl logs -f taskflow-controller-846ccc5bbb-w748q
I0101 05:14:59.301232 1 init_config.go:22] run in cluster!
{"level":"info","ts":"2024-01-01T05:14:59Z","logger":"controller-runtime.metrics","msg":"Metrics server is starting to listen","addr":":8080"}
{"level":"info","ts":"2024-01-01T05:14:59Z","logger":"task-flow operator","msg":"Starting server","path":"/metrics","kind":"metrics","addr":"[::]:8080"}
{"level":"info","ts":"2024-01-01T05:14:59Z","logger":"task-flow operator","msg":"Starting EventSource","controller":"task","controllerGroup":"api.practice.com","controllerKind":"Task","source":"kind source: *v1alpha1.Task"}
{"level":"info","ts":"2024-01-01T05:14:59Z","logger":"task-flow operator","msg":"Starting EventSource","controller":"task","controllerGroup":"api.practice.com","controllerKind":"Task","source":"kind source: *v1.Pod"}
{"level":"info","ts":"2024-01-01T05:14:59Z","logger":"task-flow operator","msg":"Starting Controller","controller":"task","controllerGroup":"api.practice.com","controllerKind":"Task"}
{"level":"info","ts":"2024-01-01T05:14:59Z","logger":"task-flow operator","msg":"Starting workers","controller":"task","controllerGroup":"api.practice.com","controllerKind":"Task","worker count":1}

I0101 05:15:21.106836 1 helper.go:130] step1 use normal mode.....
I0101 05:15:21.106857 1 helper.go:184] [--wait /etc/podinfo/order --waitcontent 1 --out stdout --command sh -c echo step1]
I0101 05:15:21.106875 1 helper.go:130] step2 use normal mode.....
I0101 05:15:21.106882 1 helper.go:184] [--wait /etc/podinfo/order --waitcontent 2 --out stdout --command sh -c echo step2]
I0101 05:15:21.106889 1 helper.go:130] step3 use normal mode.....

I0101 05:17:03.329371 1 image_helper.go:72] [devopscube/kubernetes-job-demo:latest] image is Image type image
I0101 05:17:07.804184 1 image_helper.go:85] Image Name: [devopscube/kubernetes-job-demo:latest], type: Image, os: [linux], Architecture: [amd64], Entrypoint: [[/script.sh]], Cmd: [[]]
I0101 05:17:07.804220 1 helper.go:184] [--wait /etc/podinfo/order --waitcontent 3 --out stdout --command /script.sh 100]
I0101 05:17:07.812416 1 task_controller.go:49] successful reconcile
I0101 05:17:07.824050 1 helper.go:241] pod status: Pending
I0101 05:17:07.824068 1 helper.go:242] annotation order: 0
I0101 05:17:07.824076 1 task_controller.go:49] successful reconcile
I0101 05:17:07.847943 1 helper.go:241] pod status: Pending
I0101 05:17:07.847963 1 helper.go:242] annotation order: 0
I0101 05:17:07.847971 1 task_controller.go:49] successful reconcile
I0101 05:17:09.756468 1 helper.go:241] pod status: Pending
I0101 05:17:09.756487 1 helper.go:242] annotation order: 0
I0101 05:17:09.756493 1 task_controller.go:49] successful reconcile
I0101 05:17:10.873731 1 task_controller.go:49] successful reconcile
I0101 05:17:10.873931 1 helper.go:241] pod status: Running
I0101 05:17:10.873942 1 helper.go:242] annotation order: 1
I0101 05:17:10.873949 1 task_controller.go:49] successful reconcile
I0101 05:17:12.141029 1 helper.go:241] pod status: Running
I0101 05:17:12.141048 1 helper.go:242] annotation order: 2
I0101 05:17:12.141057 1 task_controller.go:49] successful reconcile
I0101 05:17:12.141302 1 helper.go:241] pod status: Running
```


### RoadMap
8 changes: 4 additions & 4 deletions entrypoint/Dockerfile → container-agent/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ RUN go mod download
COPY main.go main.go
COPY cmd/ cmd/

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o entrypoint main.go
RUN chmod +x entrypoint
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o container-agent main.go
RUN chmod +x container-agent


FROM alpine:3.12
Expand All @@ -34,5 +34,5 @@ WORKDIR /app

#COPY --from=builder /usr/local/go/lib/time/zoneinfo.zip /app

COPY --from=builder /app/entrypoint .
ENTRYPOINT ["./entrypoint"]
COPY --from=builder /app/container-agent .
ENTRYPOINT ["./container-agent"]
4 changes: 4 additions & 0 deletions container-agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## container-agent 通用容器代理

### 设计功能:
- 用于代替并执行其他容器的代理入口
File renamed without changes.
17 changes: 9 additions & 8 deletions entrypoint/cmd/helper.go → container-agent/cmd/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (
"time"
)

// CheckFlags 检查参数
func CheckFlags() {
// ValidateFlags 检查参数
func ValidateFlags() {
if encodeFile == "" {
if waitFile == "" || out == "" || command == "" {
log.Println("error input param...")
Expand Down Expand Up @@ -54,7 +54,7 @@ func GenEncodeFile(encodefile string) error {
return nil
}

// getWaitContent 读取waitfile内容
// getWaitContent 读取 waitfile 内容
func getWaitContent() string {
f, err := os.Open(waitFile)
if err != nil {
Expand Down Expand Up @@ -84,7 +84,7 @@ func CheckWaitFile() {
}
// 此时程序要退出
if getContent == quitContent {
log.Println("任务被取消")
log.Println("task exit")
os.Exit(1) //停止程序
}
}
Expand All @@ -94,7 +94,7 @@ func CheckWaitFile() {
continue
} else {
// 其他未知错误
log.Fatal(err)
log.Fatal("unknown error: ", err)
}
}

Expand All @@ -119,7 +119,7 @@ func ExecCmdAndArgs(args []string) {
cmd := ""
// 非加密文件模式
if encodeFile == "" {
cmdList := strings.Split(command, " ") // 譬如 sh -c 这种字符串,要切割,取出第一个作为command
cmdList := strings.Split(command, " ") // sh -c 这种字符串,要切割,取出第一个作为command
cmd = cmdList[0] //肯定有值 ,所以不用判断
if len(cmdList) > 1 { //把剩余的合并到argList 前面
argList = append(argList, cmdList[1:]...)
Expand Down Expand Up @@ -152,7 +152,9 @@ func Gzip(str string) string {
log.Println(err)
return ""
}
err = gz.Close() //这里要关掉,否则取不到数据 也可手工flush.但依然要关掉gz

// 需要关闭,否则获取不到 data 也可手动 flush 最后依然需要关闭
err = gz.Close()
if err != nil {
log.Println(err)
return ""
Expand All @@ -178,6 +180,5 @@ func UnGzip(str string) string {
log.Println("read gzip error:", err)
return ""
}

return string(ret)
}
38 changes: 38 additions & 0 deletions container-agent/cmd/rootcmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cmd

import (
"github.com/spf13/cobra"
"log"
)

// 测试方式
// go run cmd/container-agent/main.go --wait ./1.txt --out out.log --command go version
// ./container-agent --out stdout --wait 1.txt --command="sh -c" "echo 123"
// ./container-agent --encodefile /xxx/xxx/1.txt
var rootCmd = &cobra.Command{
Use: "container-agent",
Short: "container agent",
Run: func(cmd *cobra.Command, args []string) {

ValidateFlags() // 检查参数合法性
CheckWaitFile() // 检查等待文件是否存在
ExecCmdAndArgs(args)

},
}

// InitCmd 初始化
func InitCmd() {
rootCmd.Flags().StringVar(&waitFile, "wait", "", "container-agent --wait /var/run/1")
// 增加了一个参数。 如果有这个参数,那么还得判断 内容是否匹配
// 如果没有这个参数,则只判断是否 有 wait 对应的文件
rootCmd.Flags().StringVar(&waitFileContent, "waitcontent", "", "container-agent --wait /var/run/1 --waitcontent 2 ")
rootCmd.Flags().StringVar(&out, "out", "", "container-agent --out /var/run/out")
rootCmd.Flags().StringVar(&command, "command", "", "container-agent --command bash")
rootCmd.Flags().StringVar(&quitContent, "quit", "-1", "container-agent --quit -2")
rootCmd.Flags().StringVar(&encodeFile, "encodefile", "", "container-agent --encodefile /var/run/abc")

if err := rootCmd.Execute(); err != nil {
log.Fatalln(err)
}
}
2 changes: 1 addition & 1 deletion entrypoint/go.mod → container-agent/go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/myoperator/entrypoint
module github.com/myoperator/container-agent

go 1.18

Expand Down
File renamed without changes.
7 changes: 7 additions & 0 deletions container-agent/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "github.com/myoperator/container-agent/cmd"

func main() {
cmd.InitCmd()
}
29 changes: 29 additions & 0 deletions deploy/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: taskflow-controller
namespace: default
spec:
selector:
matchLabels:
app: taskflow-controller
replicas: 1
template:
metadata:
labels:
app: taskflow-controller
spec:
nodeName: vm-0-16-centos # 只调度到这个节点上
serviceAccountName: taskflow-sa # 配置service account
containers:
- name: taskflow # 控制器镜像
image: taskflowoperator:v1
imagePullPolicy: IfNotPresent
env:
- name: "Release"
value: "1"
workingDir: "/app"
command: ["./taskflowoperator"]
ports:
- containerPort: 80

Loading

0 comments on commit b84c76f

Please sign in to comment.