资深DevOps工程师(PaaS方向)- 基于Golang的Kubernetes托管平台实战经验

资深DevOps工程师(PaaS方向)- 基于Golang的Kubernetes托管平台实战经验 凭借其商业应用,IONOS 是欧洲领先的主机和云应用提供商之一。凭借我们先进的技术,我们每天都能赢得来自许多不同国家的超过 800 万客户的信赖。

您的职责

  • 设计云基础设施和解决方案,为客户提供新功能。
  • 开发、改进和维护完整的工具链(例如 Helm Charts、Github Actions、GitOps)。
  • 主要使用 Golang 进行编程(Kubernetes Operators、REST API、库和工具)。
  • 自动化繁琐的任务,特别是平台的自愈机制。
  • 在自愈机制不足时,参与待命值班。

我们看重

  • 在云环境和 Kubernetes 方面拥有丰富的经验。
  • 在运维和故障排除生产环境方面拥有丰富的经验,包括监控、告警和日志分析。
  • 具备编程经验,包括编写、审查、测试和部署精心设计的代码。
  • 具备 Linux 操作系统经验。
  • 具备网络基础知识经验。

附加信息

IONOS PaaS 托管 Kubernetes 团队正在寻找一位积极主动且经验丰富的 DevOps 工程师。

PaaS 托管 Kubernetes 团队负责为客户开发和维护托管 Kubernetes 服务。我们利用 Kubernetes Operators 来管理 IONOS 云基础设施,以提供和维护可靠、地理冗余的 Kubernetes 集群。我们负责企业客户大量节点和集群的生命周期管理,持续更新 Kubernetes 堆栈以及我们自己的驱动程序,如 Cloud Controller Manager 和 Container Storage Interface。

我们的小团队负责服务的整个生命周期:我们构建它、交付它、运行它。我们正在寻找一位能够加入我们团队,并与我们共同努力提供最佳产品的人选。

在此申请


更多关于资深DevOps工程师(PaaS方向)- 基于Golang的Kubernetes托管平台实战经验的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于资深DevOps工程师(PaaS方向)- 基于Golang的Kubernetes托管平台实战经验的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个非常典型的基于Golang的Kubernetes Operator开发岗位,专注于PaaS级别的Kubernetes托管服务。核心工作围绕使用Go编写和维护Kubernetes控制器/Operator,以实现云基础设施的声明式管理和自动化。

以下是一个简化的Go代码示例,展示了此类岗位可能涉及的核心模式:一个自定义资源(Custom Resource)的控制器Reconcile逻辑。这常用于管理集群生命周期,如节点池或集群配置。

package controllers

import (
    "context"
    "fmt"
    "time"

    "github.com/go-logr/logr"
    "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/reconcile"

    paasv1alpha1 "your-company.com/paas/api/v1alpha1"
)

// ManagedClusterReconciler reconciles a ManagedCluster object
type ManagedClusterReconciler struct {
    client.Client
    Log    logr.Logger
    Scheme *runtime.Scheme
    // 通常会注入云服务商SDK客户端,用于调用IaaS层API(如IONOS Cloud API)
    // CloudClient *ionoscloud.APIClient
}

// +kubebuilder:rbac:groups=paas.your-company.com,resources=managedclusters,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=paas.your-company.com,resources=managedclusters/status,verbs=get;update;patch

func (r *ManagedClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    log := r.Log.WithValues("managedcluster", req.NamespacedName)

    // 1. 获取自定义资源对象
    var cluster paasv1alpha1.ManagedCluster
    if err := r.Get(ctx, req.NamespacedName, &cluster); err != nil {
        if errors.IsNotFound(err) {
            // 对象已被删除,触发清理逻辑
            log.Info("ManagedCluster resource not found. Assuming it was deleted.")
            // 调用云API清理对应的基础设施资源(如虚拟机、负载均衡器、网络)
            // err := r.CloudClient.DeleteCluster(ctx, req.Name)
            return reconcile.Result{}, nil
        }
        log.Error(err, "Failed to get ManagedCluster")
        return reconcile.Result{}, err
    }

    // 2. 检查资源状态,判断是否需要执行操作
    if cluster.Status.Phase == paasv1alpha1.PhaseProvisioned {
        log.V(1).Info("Cluster already provisioned, checking for drift or updates.")
        // 此处可添加检查配置漂移或处理更新的逻辑
    }

    // 3. 根据Spec中的期望状态,调用底层云API创建或更新资源
    switch cluster.Status.Phase {
    case "", paasv1alpha1.PhasePending:
        log.Info("Provisioning new cluster")
        cluster.Status.Phase = paasv1alpha1.PhaseProvisioning
        if err := r.Status().Update(ctx, &cluster); err != nil {
            log.Error(err, "Failed to update cluster status to Provisioning")
            return reconcile.Result{}, err
        }

        // 模拟调用云提供商API创建Kubernetes集群
        // createdCluster, err := r.CloudClient.CreateCluster(ctx, cluster.Spec)
        // if err != nil { ... }
        log.Info("Calling cloud API to create cluster resources")

        // 模拟创建成功,更新状态
        cluster.Status.Phase = paasv1alpha1.PhaseProvisioned
        cluster.Status.APIEndpoint = "https://api.cluster.example.com:6443"
        cluster.Status.Conditions = append(cluster.Status.Conditions, paasv1alpha1.ClusterCondition{
            Type:   paasv1alpha1.ConditionReady,
            Status: "True",
            LastUpdateTime: metav1.Now(),
        })
        if err := r.Status().Update(ctx, &cluster); err != nil {
            log.Error(err, "Failed to update cluster status to Provisioned")
            return reconcile.Result{}, err
        }
        log.Info("Cluster provisioned successfully")

    case paasv1alpha1.PhaseDeleting:
        log.Info("Deleting cluster")
        // 调用云API删除资源
        // err := r.CloudClient.DeleteCluster(ctx, cluster.Name)
        // if err != nil { ... }
        // 从Kubernetes中移除finalizer,允许资源对象被删除
        // controllerutil.RemoveFinalizer(&cluster, "managedcluster.paas.your-company.com/finalizer")
        // if err := r.Update(ctx, &cluster); err != nil { ... }
        return reconcile.Result{}, nil
    }

    // 4. 如果需要重试或定期协调,返回带有RequeueAfter的结果
    // 例如,在集群创建过程中,定期检查云提供商任务状态
    if cluster.Status.Phase == paasv1alpha1.PhaseProvisioning {
        return reconcile.Result{RequeueAfter: 30 * time.Second}, nil
    }

    return reconcile.Result{}, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *ManagedClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
    return ctrl.NewControllerManagedBy(mgr).
        For(&paasv1alpha1.ManagedCluster{}).
        Complete(r)
}

对应的自定义资源定义(CRD)示例:

# api/v1alpha1/managedcluster_types.go 结构体定义(Kubebuilder风格)
package v1alpha1

import (
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ManagedClusterSpec defines the desired state of ManagedCluster
type ManagedClusterSpec struct {
    // Kubernetes版本
    Version string `json:"version"`
    // 节点池配置
    NodePools []NodePoolSpec `json:"nodePools"`
    // 区域配置
    Location string `json:"location"`
    // 网络CIDR
    NetworkCIDR string `json:"networkCIDR,omitempty"`
}

// ManagedClusterStatus defines the observed state of ManagedCluster
type ManagedClusterStatus struct {
    // 当前阶段:Pending, Provisioning, Provisioned, Failed, Deleting
    Phase string `json:"phase,omitempty"`
    // Kubernetes API端点
    APIEndpoint string `json:"apiEndpoint,omitempty"`
    // 条件状态数组
    Conditions []ClusterCondition `json:"conditions,omitempty"`
}

type ClusterCondition struct {
    Type               string             `json:"type"`
    Status             string             `json:"status"` // "True", "False", "Unknown"
    LastUpdateTime     metav1.Time        `json:"lastUpdateTime,omitempty"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase"
// +kubebuilder:printcolumn:name="Endpoint",type="string",JSONPath=".status.apiEndpoint"

// ManagedCluster is the Schema for the managedclusters API
type ManagedCluster struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   ManagedClusterSpec   `json:"spec,omitempty"`
    Status ManagedClusterStatus `json:"status,omitempty"`
}

此外,团队通常还需要开发并维护Cloud Controller Manager(CCM)和CSI驱动,以下是一个CSI节点服务NodePublishVolume方法的简化示例,用于将卷挂载到Pod中:

package driver

import (
    "fmt"
    "os"
    "path/filepath"

    "github.com/container-storage-interface/spec/lib/go/csi"
    "golang.org/x/net/context"
    "k8s.io/klog/v2"
    "k8s.io/utils/mount"
)

func (d *Driver) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) {
    targetPath := req.GetTargetPath()
    stagingPath := req.GetStagingTargetPath()

    // 1. 参数验证
    if req.GetVolumeCapability() == nil {
        return nil, status.Error(codes.InvalidArgument, "Volume capability missing in request")
    }

    // 2. 检查挂载点是否已存在
    notMnt, err := d.mounter.IsLikelyNotMountPoint(targetPath)
    if err != nil {
        if os.IsNotExist(err) {
            if err := os.MkdirAll(targetPath, 0750); err != nil {
                return nil, status.Errorf(codes.Internal, "Could not create target directory: %v", err)
            }
            notMnt = true
        } else {
            return nil, status.Errorf(codes.Internal, "Could not check mount point: %v", err)
        }
    }
    if !notMnt {
        // 已经挂载,直接返回成功
        return &csi.NodePublishVolumeResponse{}, nil
    }

    // 3. 执行挂载(假设是块设备)
    fsType := req.GetVolumeCapability().GetMount().GetFsType()
    options := req.GetVolumeCapability().GetMount().GetMountFlags()

    // 从staging路径挂载到目标路径
    err = d.mounter.Mount(stagingPath, targetPath, fsType, options)
    if err != nil {
        return nil, status.Errorf(codes.Internal, "Could not mount %q at %q: %v", stagingPath, targetPath, err)
    }

    klog.Infof("Volume %s successfully mounted to %s", req.VolumeId, targetPath)
    return &csi.NodePublishVolumeResponse{}, nil
}

这个岗位要求工程师深入理解Kubernetes控制循环、自定义资源定义、控制器运行时以及Go并发模式,同时需要将云基础设施API(如IONOS Cloud API)与Kubernetes Operator模式紧密结合,实现大规模集群的声明式自动化管理。

回到顶部