Golang日志服务开发工程师职位讨论 - Unitet Internet技术团队招募

Golang日志服务开发工程师职位讨论 - Unitet Internet技术团队招募 IONOS凭借其商业应用,是欧洲领先的主机和云应用提供商之一。凭借我们先进的技术,我们每天都能赢得来自许多不同国家的超过800万客户的信赖。

您的职责

在IONOS,您将与欧洲领先的云基础设施、云服务和托管服务提供商的不同团队合作。我们为您提供在最具未来前景的行业之一发展的机会。我们以开放的结构、文化和扁平化的层级以及无与伦比的团队精神为特点。我们坚信工作与乐趣可以结合,并为您提供相应的环境。随着业务的持续增长,我们一直在寻找新的同事。我们正在为我们的“日志即服务”团队寻找增援力量。该团队专注于为客户开发和维护日志管理服务。这些服务范围涵盖从日志代理(如Fluent Bit和rsyslog)到日志处理器、数据库以及其他日志分析产品。与其他团队一起,LaaS团队负责我们日志服务的整个生命周期——从构建到交付和运营。加入IONOS,让我们共同成长。

  • 使用(主要)Golang进行编程(Kubernetes Operators、REST API、库和其他工具)。
  • 设计解决方案并为我们的客户提供新功能。
  • 开发、改进和维护完整的工具链(例如 Helm Charts、Github Actions、GitOps)。
  • 扎实的应用性能检测技能(例如日志记录、追踪、性能剖析、监控)。
  • 在云环境(Kubernetes)中定义服务结构。
  • 与团队一起重新思考服务架构,并使用Golang实现组件。

我们看重

  • 具备开发、测试、评审和部署高质量工程代码的经验,最好是使用Golang。
  • 您拥有使用Kubernetes或AWS等云技术的实践经验。
  • 具备Kubernetes容器编排、Kubernetes Operators、控制器、CRD和Helm Charts的经验。
  • 具备运维和故障排除生产环境的经验,包括监控、告警和日志分析。
  • 具备Linux操作系统经验。
  • 您不犹豫提问,但也喜欢自己解决问题,始终保持适应性强和以解决方案为导向的心态。
  • 您具备出色的英语口语、书面和演示技能。

在此申请


更多关于Golang日志服务开发工程师职位讨论 - Unitet Internet技术团队招募的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang日志服务开发工程师职位讨论 - Unitet Internet技术团队招募的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个非常典型的Go语言云原生/基础设施开发职位,专注于日志服务(Logging as a Service)。职位描述清晰地勾勒出一个现代云服务团队的技术栈和职责范围。以下是对其技术要点的分析和相关Go代码示例:

1. Kubernetes Operators 和控制器开发 这是该职位的核心。Operator用于扩展Kubernetes API,管理自定义资源(CRD)以控制日志服务的生命周期(如Fluent Bit配置、日志管道)。

// 示例:一个简化的LogPipeline Operator Reconciler核心逻辑
package controller

import (
    "context"
    "fmt"
    appsv1 "k8s.io/api/apps/v1"
    corev1 "k8s.io/api/core/v1"
    "k8s.io/apimachinery/pkg/api/errors"
    "k8s.io/apimachinery/pkg/runtime"
    ctrl "sigs.k8s.io/controller-runtime"
    "sigs.k8s.io/controller-runtime/pkg/client"
    "sigs.k8s.io/controller-runtime/pkg/log"

    laasv1alpha1 "github.com/ionos/laas-operator/api/v1alpha1"
)

type LogPipelineReconciler struct {
    client.Client
    Scheme *runtime.Scheme
}

func (r *LogPipelineReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    logger := log.FromContext(ctx)

    // 1. 获取自定义资源 LogPipeline
    var pipeline laasv1alpha1.LogPipeline
    if err := r.Get(ctx, req.NamespacedName, &pipeline); err != nil {
        if errors.IsNotFound(err) {
            logger.Info("LogPipeline resource not found. Ignoring since object must be deleted")
            return ctrl.Result{}, nil
        }
        logger.Error(err, "Failed to get LogPipeline")
        return ctrl.Result{}, err
    }

    // 2. 检查并创建对应的Fluent Bit DaemonSet
    var ds appsv1.DaemonSet
    err := r.Get(ctx, req.NamespacedName, &ds)
    if err != nil && errors.IsNotFound(err) {
        // 创建 DaemonSet
        logger.Info("Creating a new DaemonSet", "DaemonSet.Namespace", req.Namespace, "DaemonSet.Name", req.Name)
        ds = *constructFluentBitDaemonSet(&pipeline)
        if err := r.Create(ctx, &ds); err != nil {
            logger.Error(err, "Failed to create new DaemonSet")
            return ctrl.Result{}, err
        }
        // DaemonSet创建成功 - 返回并重入
        return ctrl.Result{Requeue: true}, nil
    } else if err != nil {
        logger.Error(err, "Failed to get DaemonSet")
        return ctrl.Result{}, err
    }

    // 3. 确保DaemonSet规格与自定义资源一致(更新逻辑)
    // ... 比较并更新 DaemonSet 的代码 ...

    return ctrl.Result{}, nil
}

func (r *LogPipelineReconciler) SetupWithManager(mgr ctrl.Manager) error {
    return ctrl.NewControllerManagedBy(mgr).
        For(&laasv1alpha1.LogPipeline{}).
        Owns(&appsv1.DaemonSet{}).
        Complete(r)
}

func constructFluentBitDaemonSet(pipeline *laasv1alpha1.LogPipeline) *appsv1.DaemonSet {
    // 根据pipeline.Spec构建Fluent Bit DaemonSet的详细定义
    // 例如,镜像、配置卷、环境变量等
    return &appsv1.DaemonSet{
        // ... DaemonSet 规格定义 ...
    }
}

2. REST API 开发 用于提供日志服务的控制平面API,管理日志管道、查询配置等。

// 示例:使用Gin框架提供日志管道管理的REST API端点
package main

import (
    "net/http"
    "github.com/gin-gonic/gin"
    "k8s.io/client-go/kubernetes"
)

type PipelineHandler struct {
    k8sClient kubernetes.Interface
}

func (h *PipelineHandler) CreatePipeline(c *gin.Context) {
    var req CreatePipelineRequest
    if err := c.ShouldBindJSON(&req); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    // 1. 验证请求
    // 2. 通过Kubernetes Client创建或更新对应的LogPipeline CRD
    // 3. 返回操作结果
    pipelineCR := buildLogPipelineCR(req)
    // ... 使用 h.k8sClient 与Kubernetes API交互 ...

    c.JSON(http.StatusAccepted, gin.H{
        "message": "Pipeline creation accepted",
        "name":    pipelineCR.Name,
    })
}

func (h *PipelineHandler) GetPipelineStatus(c *gin.Context) {
    name := c.Param("name")
    namespace := c.Param("namespace")

    // 通过Kubernetes Client获取LogPipeline CRD状态
    // 并聚合其管理的Pod(Fluent Bit实例)的状态
    status := h.aggregatePipelineStatus(namespace, name)
    
    c.JSON(http.StatusOK, status)
}

func main() {
    r := gin.Default()
    handler := &PipelineHandler{}

    api := r.Group("/api/v1")
    {
        api.POST("/pipelines", handler.CreatePipeline)
        api.GET("/namespaces/:namespace/pipelines/:name/status", handler.GetPipelineStatus)
    }
    r.Run(":8080")
}

3. 性能检测与可观测性集成 职位要求“扎实的应用性能检测技能”,这在Go中通常通过结构化日志、指标暴露和分布式追踪实现。

// 示例:在服务中集成OpenTelemetry进行追踪和指标收集
package main

import (
    "context"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/attribute"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
    "go.opentelemetry.io/otel/exporters/prometheus"
    "go.opentelemetry.io/otel/metric"
    "go.opentelemetry.io/otel/metric/global"
    "go.opentelemetry.io/otel/propagation"
    "go.opentelemetry.io/otel/sdk/metric"
    "go.opentelemetry.io/otel/sdk/resource"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
    semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
    "google.golang.org/grpc"
    "log"
    "time"
)

func initTracer() (*sdktrace.TracerProvider, error) {
    // 创建OTLP gRPC导出器(通常指向Jaeger或OTLP Collector)
    traceExporter, err := otlptracegrpc.New(context.Background(),
        otlptracegrpc.WithInsecure(),
        otlptracegrpc.WithEndpoint("otel-collector:4317"),
    )
    if err != nil {
        return nil, err
    }

    tp := sdktrace.NewTracerProvider(
        sdktrace.WithBatcher(traceExporter),
        sdktrace.WithResource(resource.NewWithAttributes(
            semconv.SchemaURL,
            semconv.ServiceName("laas-api"),
            attribute.String("environment", "production"),
        )),
    )
    otel.SetTracerProvider(tp)
    otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
    return tp, nil
}

func initMeter() (*metric.MeterProvider, error) {
    // 设置Prometheus指标导出器
    exporter, err := prometheus.New()
    if err != nil {
        return nil, err
    }

    mp := metric.NewMeterProvider(metric.WithReader(exporter))
    global.SetMeterProvider(mp)
    return mp, nil
}

func processLogBatch(ctx context.Context) {
    tracer := otel.Tracer("laas-processor")
    meter := global.Meter("laas-processor")

    // 创建一个计数器指标
    logsProcessed, _ := meter.Int64Counter(
        "logs_processed_total",
        metric.WithDescription("Total number of processed log entries"),
    )

    // 创建一个直方图指标
    processDuration, _ := meter.Float64Histogram(
        "log_batch_process_duration_seconds",
        metric.WithDescription("Duration of log batch processing"),
    )

    ctx, span := tracer.Start(ctx, "processLogBatch")
    defer span.End()

    start := time.Now()
    
    // 模拟处理逻辑
    time.Sleep(10 * time.Millisecond)
    batchSize := int64(1000)

    // 记录属性到Span
    span.SetAttributes(
        attribute.Int64("log.batch.size", batchSize),
        attribute.String("log.source", "k8s.container"),
    )

    // 增加计数器
    logsProcessed.Add(ctx, batchSize)
    
    // 记录直方图
    duration := time.Since(start).Seconds()
    processDuration.Record(ctx, duration)

    // 记录结构化日志(与追踪关联)
    log.Printf("Processed log batch. size=%d, duration=%.3fs, traceID=%s", 
        batchSize, duration, span.SpanContext().TraceID().String())
}

4. Helm Charts 与 GitOps 团队负责“完整的工具链”,包括Helm Charts。Go常用于编写Helm模板的测试工具或辅助程序。

// 示例:使用Go验证Helm Chart值的简单工具
package main

import (
    "fmt"
    "gopkg.in/yaml.v3"
    "io/ioutil"
    "os"
)

type ChartValues struct {
    ReplicaCount int `yaml:"replicaCount"`
    Image        struct {
        Repository string `yaml:"repository"`
        Tag        string `yaml:"tag"`
        PullPolicy string `yaml:"pullPolicy"`
    } `yaml:"image"`
    FluentBit struct {
        Config string `yaml:"config"`
        Parsers string `yaml:"parsers"`
    } `yaml:"fluentBit"`
}

func validateValues(valuesPath string) error {
    data, err := ioutil.ReadFile(valuesPath)
    if err != nil {
        return fmt.Errorf("failed to read values file: %w", err)
    }

    var values ChartValues
    if err := yaml.Unmarshal(data, &values); err != nil {
        return fmt.Errorf("failed to unmarshal YAML: %w", err)
    }

    // 执行验证规则
    if values.ReplicaCount <= 0 {
        return fmt.Errorf("replicaCount must be positive, got %d", values.ReplicaCount)
    }
    if values.Image.Repository == "" {
        return fmt.Errorf("image.repository is required")
    }
    if values.FluentBit.Config == "" {
        return fmt.Errorf("fluentBit.config is required")
    }

    fmt.Println("Values validation passed")
    return nil
}

func main() {
    if err := validateValues("values.yaml"); err != nil {
        fmt.Fprintf(os.Stderr, "Validation error: %v\n", err)
        os.Exit(1)
    }
}

这个职位要求的技术组合(Go、Kubernetes Operators、云原生可观测性、基础设施即代码)代表了当前企业级云服务开发的典型要求。代码示例展示了在这些领域使用Go的实际模式。

回到顶部