Skip to content

Commit

Permalink
๐Ÿš€ ้‡‡้›†้€ป่พ‘้‡ๆž„
Browse files Browse the repository at this point in the history
๐Ÿš€ ้‡‡้›†้€ป่พ‘้‡ๆž„
  • Loading branch information
Cairry committed Dec 27, 2024
1 parent 14a4701 commit 7e55e81
Show file tree
Hide file tree
Showing 33 changed files with 1,043 additions and 1,457 deletions.
56 changes: 42 additions & 14 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,52 @@ jobs:
- name: Checkout code
uses: actions/checkout@v3

- name: 1. Set env
run: |
echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_ENV
echo "SHORT_SHA=$(echo ${GITHUB_SHA:0:4})" >> $GITHUB_ENV
echo "DATE=$(TZ=Asia/Shanghai date +%Y-%m-%d.%H-%M-%S)" >> $GITHUB_ENV
- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: 2. Build Docker image
run: |
docker build -t cairry/watchlog:$BRANCH_NAME.$DATE.$SHORT_SHA .
docker tag cairry/watchlog:$BRANCH_NAME.$DATE.$SHORT_SHA cairry/watchlog:latest
- name: Inject slug/short variables
uses: rlespinasse/github-slug-action@v4

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3

- name: Available platforms
run: echo ${{ steps.buildx.outputs.platforms }}

- name: 3. Login to Docker Hub
uses: docker/login-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: 4. Push Docker image to Docker Hub
- name: Login to Aliyun Hub
uses: docker/login-action@v3
with:
registry: registry.cn-hangzhou.aliyuncs.com
username: ${{ secrets.OPSRE_ALIHUB_USERNAME }}
password: ${{ secrets.OPSRE_ALIHUB_TOKEN }}

- name: Set env variables
id: set_env
run: |
docker push cairry/watchlog:latest
docker push cairry/watchlog:$BRANCH_NAME.$DATE.$SHORT_SHA
echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}"
echo "SHORT_SHA=${GITHUB_SHA:0:4}"
echo "DATE=$(TZ=Asia/Shanghai date +%Y-%m-%d.%H-%M-%S)"
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
# ๆ‰€้œ€่ฆ็š„ไฝ“็ณป็ป“ๆž„๏ผŒๅฏไปฅๅœจ Available platforms ๆญฅ้ชคไธญ่Žทๅ–ๆ‰€ๆœ‰็š„ๅฏ็”จๆžถๆž„
platforms: linux/arm64,linux/amd64
# ้•œๅƒๆŽจ้€ๆ—ถ้—ด
push: ${{ github.event_name != 'pull_request' }}
build-args: |
VERSION=${{ env.DATE }}
tags: |
cairry/watchlog:latest
cairry/watchlog:${{ env.BRANCH_NAME }}_${{ env.DATE }}_${{ env.SHORT_SHA }}
registry.cn-hangzhou.aliyuncs.com/opsre/watchlog:latest
registry.cn-hangzhou.aliyuncs.com/opsre/watchlog:${{ env.BRANCH_NAME }}_${{ env.DATE }}_${{ env.SHORT_SHA }}
24 changes: 8 additions & 16 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM registry.js.design/base/golang:1.18-alpine3.16 AS build
FROM registry.cn-hangzhou.aliyuncs.com/opsre/golang:1.21.9-alpine3.19 AS build

ENV GO111MODULE=on \
CGO_ENABLED=0 \
Expand All @@ -11,29 +11,21 @@ COPY . /workspace
WORKDIR /workspace

RUN go mod tidy && \
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o point ./main.go && \
chmod 777 point
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o watchlog ./main.go && \
chmod 777 watchlog

FROM elastic/filebeat:7.17.10
FROM registry.js.design/library/filebeat:7.17.10_python2

USER root
COPY --from=build /workspace/watchlog /usr/share/filebeat/watchlog/watchlog

COPY --from=build /workspace/point /usr/share/filebeat/point/point
COPY assets/entrypoint assets/filebeat/ assets/healthz /usr/share/filebeat/watchlog/

COPY assets/entrypoint assets/filebeat/ assets/healthz /usr/share/filebeat/point/

RUN apt-get update && \
apt-get -y install python2 && \
/usr/bin/chmod +x /usr/share/filebeat/point/point /usr/share/filebeat/point/healthz /usr/share/filebeat/point/config.filebeat
RUN /usr/bin/chmod +x /usr/share/filebeat/watchlog/watchlog /usr/share/filebeat/watchlog/healthz /usr/share/filebeat/watchlog/config.filebeat

HEALTHCHECK CMD /usr/share/filebeat/healthz

VOLUME /var/log/filebeat

VOLUME /var/lib/filebeat

WORKDIR /usr/share/filebeat/

ENV PILOT_TYPE=filebeat

ENTRYPOINT ["python2", "/usr/share/filebeat/point/entrypoint"]
ENTRYPOINT ["python2", "/usr/share/filebeat/watchlog/entrypoint"]
29 changes: 0 additions & 29 deletions README.md

This file was deleted.

6 changes: 3 additions & 3 deletions assets/entrypoint
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ def cleanup():
def run():
pilot_type = os.environ.get(ENV_PILOT_TYPE)
if pilot_filebeat == pilot_type:
tpl_config = "/usr/share/filebeat/point/filebeat.tpl"
tpl_config = "/usr/share/filebeat/watchlog/filebeat.tpl"

os.execve('/usr/share/filebeat/point/point', ['/usr/share/filebeat/point/point', '-template', tpl_config, '-base', base, '-log-level', 'debug'],
os.execve('/usr/share/filebeat/watchlog/watchlog', ['/usr/share/filebeat/watchlog/watchlog', '-template', tpl_config],
os.environ)


def config():
pilot_type = os.environ.get(ENV_PILOT_TYPE)
if pilot_filebeat == pilot_type:
print "start log-pilot:", pilot_filebeat
subprocess.check_call(['/usr/share/filebeat/point/config.filebeat'])
subprocess.check_call(['/usr/share/filebeat/watchlog/config.filebeat'])


if __name__ == '__main__':
Expand Down
7 changes: 0 additions & 7 deletions assets/filebeat/filebeat.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,16 @@
json.keys_under_root: true
{{end}}
fields:
{{range $key, $value := .CustomFields}}
{{ $key }}: {{ $value }}
{{end}}
{{range $key, $value := .Tags}}
{{ $key }}: {{ $value }}
{{end}}
{{range $key, $value := $.container}}
{{ $key }}: {{ $value }}
{{end}}
{{range $key, $value := .CustomConfigs}}
{{ $key }}: {{ $value }}
{{end}}
tail_files: false
close_inactive: 2h
close_eof: false
close_removed: true
clean_removed: true
close_renamed: false

{{end}}
168 changes: 168 additions & 0 deletions controller/containerd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package controller

import (
"context"
"encoding/json"
"fmt"
"github.com/containerd/containerd"
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/oci"
"github.com/zeromicro/go-zero/core/logc"
"io"
"regexp"
"strings"
"watchlog/pkg/ctx"
"watchlog/pkg/runtime"
)

var (
create = "containerd.events.ContainerCreate"
delete = "containerd.events.ContainerDelete"
)

type Containerd struct {
ctx *ctx.Context
}

func NewContainerInterface(ctx *ctx.Context) InterRuntime {
return &Containerd{
ctx: ctx,
}
}

func (c Containerd) ProcessContainers() error {
c.ctx.Lock()
defer c.ctx.Unlock()

containerCtx := namespaces.WithNamespace(c.ctx.Context, "k8s.io")
c.watchEvent(c.ctx, containerCtx)

containers, err := c.ctx.ContainerdCli.Containers(containerCtx)
if err != nil {
logc.Errorf(context.Background(), fmt.Sprintf("get containers failed, %s", err.Error()))
return err
}

for _, container := range containers {
if err := c.processContainer(containerCtx, container); err != nil {
logc.Errorf(context.Background(), "process container failed: %v", err)
}
}

return nil
}

func (c Containerd) processContainer(containerCtx context.Context, container containerd.Container) error {
meta, err := container.Info(containerCtx)
if err != nil {
return fmt.Errorf("get container meta info failed: %s", err.Error())
}

spec, err := container.Spec(containerCtx)
if err != nil {
return fmt.Errorf("get container spec failed: %s", err.Error())
}

return processCollectFile(c.ctx, spec.Process.Env, meta)
}

func (c Containerd) watchEvent(ctx *ctx.Context, containerCtx context.Context) {
msgs, errs := c.ctx.ContainerdCli.EventService().Subscribe(containerCtx, "")

go func() {
defer logc.Info(context.Background(), "finish to watch containerd event")
logc.Infof(context.Background(), "begin to watch containerd event")

for {
select {
case msg := <-msgs:
if err := c.processEvent(ctx, containerCtx, msg); err != nil {
logc.Errorf(context.Background(), "process event failed: %v", err)
}
case err := <-errs:
if err == io.EOF || err == io.ErrUnexpectedEOF {
return
}
logc.Errorf(context.Background(), "event subscription error: %v", err)
}
}
}()
}

func (c Containerd) processEvent(ctx *ctx.Context, containerCtx context.Context, msg *events.Envelope) error {
v := string(msg.Event.GetValue())
s := strings.TrimPrefix(v, "\n@")
containerId := removeSpecialChars(s)
containerId = strings.Split(containerId, "-")[0]

t := msg.Event.GetTypeUrl()
switch t {
case create:
if Exists(ctx, containerId) {
return nil
}

_, err := ctx.ContainerdCli.LoadContainer(containerCtx, containerId)
if err != nil {
if errdefs.IsNotFound(err) {
_, err = ctx.ContainerdCli.LoadContainer(containerCtx, containerId)
}

return err
}

meta, err := ctx.ContainerdCli.ContainerService().Get(containerCtx, containerId)
if err != nil {
return err
}

var spec oci.Spec
err = json.Unmarshal(meta.Spec.GetValue(), &spec)
if err != nil {
return err
}

err = processCollectFile(ctx, spec.Process.Env, meta)
if err != nil {
return err
}

return err

case delete:
logc.Infof(context.Background(), "Process container destroy event: %s", containerId)

err := DelContainerLogFile(ctx, containerId)
if err != nil {
logc.Errorf(context.Background(), fmt.Sprintf("Process container destroy event error: %s, %s", containerId, err.Error()))
}
}
return nil
}

func processCollectFile(c *ctx.Context, envs []string, meta containers.Container) error {
// ็ฌฆๅˆๆกไปถ็š„ Env
var logEnvs []string
for _, envVar := range envs {
// LogPrefix: aliyun_logs_tencent-prod-hermione=stdout ,envVar: aliyun_logs
if strings.HasPrefix(envVar, c.LogPrefix) {
logEnvs = append(logEnvs, envVar)
}
}

fields := CollectFields{
Id: meta.ID,
Env: logEnvs,
Labels: meta.Labels,
LogPath: fmt.Sprintf("%s_%s_*/%s/*.log", meta.Labels[runtime.KubernetesContainerNamespace], meta.Labels[runtime.KubernetesPodName], meta.Labels[runtime.KubernetesContainerName]),
}
return NewCollectFile(c, fields)
}

func removeSpecialChars(str string) string {
re := regexp.MustCompile(`[^a-zA-Z0-9]+`)
return re.ReplaceAllString(str, "-")
}
Loading

0 comments on commit 7e55e81

Please sign in to comment.