中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Kubernetes如何在yaml中編程

發布時間:2022-01-12 16:14:39 來源:億速云 閱讀:131 作者:柒染 欄目:云計算

本篇文章給大家分享的是有關Kubernetes如何在yaml中編程,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

引子

性能測試在日常的開發工作中是常規需求,用來摸底服務的性能。

那么如何做性能測試?要么是通過編碼的方式完成,寫一堆腳本,用完即棄;要么是基于平臺,在平臺定義的流程中進行。對于后者,通常由于目標場景的復雜性,如部署特定的 workload、觀測特定的性能項、網絡訪問問題等,往往導致性能測試平臺要以高成本才能滿足不斷變化的開發場景的需求。

在云原生的背景下,是否可以更好解決這種問題?

先看兩個 yaml 文件:

  • performance-test.yaml 描述了在 K8s 中的操作流程:

    1. 創建測試用的 Namespace

    2. 啟動針對 Deployment 創建效率和創建成功率的監控

    3. 下述動作重復 N 次:① 使用 workload 模板創建 Deployment;② 等待 Deployment 變為 Ready

    4. 刪除測試用的 Namespace

  • basic-1-pod-deployment.yaml 描述使用的 workload 模板

performance-test.yaml :

apiVersion: aliyun.com/v1alpha1kind: Beidoumetadata:  name: performance  namespace: beidouspec:  steps:
  - name: "Create Namespace If Not Exits"operations:
    - name: "create namespace"  type: Task      op: CreateNamespace      args:
      - name: NSvalue: beidou
  - name: "Monitor Deployment Creation Efficiency"operations:
    - name: "Begin To Monitor Deployment Creation Efficiency"  type: Task      op: DeploymentCreationEfficiency      args:
      - name: NSvalue: beidou
    - name: "Repeat 1 Times"  type: Task      op: RepeatNTimes      args:
      - name: TIMESvalue: "1"  - name: ACTIONreference:          id: deployment-operation
  - name: "Delete namespace"operations:
    - name: "delete namespace"  type: Task      op: DeleteNamespace      args:
      - name: NSvalue: beidou
      - name: FORCEvalue: "false"
  references:
  - id: deployment-operationsteps:
    - name: "Prepare Deployment"  operations:
      - name: "Prepare Deployment"type: Taskop: PrepareBatchDeploymentsargs:
        - name: NS          value: beidou
        - name: NODE_TYPE          value: ebm
        - name: BATCH_NUM          value: "1"- name: TEMPLATE          value: "./templates/basic-1-pod-deployment.yaml"- name: DEPLOYMENT_REPLICAS          value: "1"- name: DEPLOYMENT_PREFIX          value: "ebm"  - name: "Wait For Deployments To Be Ready"type: Taskop: WaitForBatchDeploymentsReadyargs:
        - name: NS          value: beidou
        - name: TIMEOUT          value: "3m"- name: CHECK_INTERVAL          value: "2s"

basic-1-pod-deployment.yaml:

apiVersion: apps/v1kind: Deploymentmetadata:  labels:app: basic-1-podspec:  selector:matchLabels:      app: basic-1-pod  template:metadata:      labels:app: basic-1-podspec:      containers:
      - name: nginximage: registry-vpc.cn-hangzhou.aliyuncs.com/xxx/nginx:1.17.9imagePullPolicy: Alwaysresources:          limits:cpu: 2memory: 4Gi

然后通過一個命令行工具執行 performance-test.yaml:

$ beidou server -c ~/.kube/config services/performance-test.yaml

執行效果如下 (每個 Deployment 創建耗時,所有 Deployment 創建耗時的 TP95 值,每個 Deployment 是否創建成功)。

這些 metrics 是按照 Prometheus 標準輸出,可以被 Prometheus server 收集走,再結合 Grafana 可以可視化展示性能測試數據。

通過在 yaml 中表達想法,編排對 K8s 資源的操作、監控,再也不用為性能測試的實現頭疼了 :D

為什么要在 yaml 中編程?

性能測試、回歸測試等對于服務質量保障有很大幫助,需要做,但常規的實現方法在初期需要投入較多的時間和精力,新增變更后維護成本比較高。

通常這個過程是以代碼的方式實現原子操作,如創建 Deployment、檢測 Pod 配置等,然后再組合原子操作來滿足需求,如 創建 Deployment -> 等待 Deployment ready -> 檢測 Pod 配置等。

有沒有辦法在實現的過程中既可以盡量低成本實現,又可以復用已有的經驗?

可以將原子操作封裝為原語,如 CreateDeployment、CheckPod,再通過 yaml 的結構表達流程,那么就可以通過 yaml 而非代碼的方式描述想法,又可以復用他人已經寫好的 yaml 文件來解決某類場景的需求。

即在 yaml 中編程,減少重復性代碼工作,通過 聲明式 的方式描述邏輯,并以 yaml 文件來滿足場景級別的復用。

業界有很多種類型的 聲明式操作 服務,如運維領域中的 Ansible、SaltStack,Kubernetes 中的Argo Workflow、clusterloader2。它們的思想整體比較類似,將高頻使用的操作封裝為原語,使用者通過原語來表述操作邏輯。

通過聲明式的方法,將面向 K8s 的操作抽象成 yaml 中的關鍵詞,在 yaml 中提供串行、并行等控制邏輯,那么就可以通過 yaml 文件完整描述想要進行的工作。

這種思想和 Argo Workflow 比較像,但粒度比 Argo 更細,關注在操作函數上:

Kubernetes如何在yaml中編程

下面簡單描述該服務的設計和實現。

設計和實現

1. 服務形態

  • 使用者在 yaml 中,通過 聲明式 的方式描述操作邏輯;

  • 以 all-in-one 的二進制工具或 Operator 的方式交付;

  • 服務內置常見原語的實現,以關鍵字的方式在 yaml 中提供;

  • 支持配置原生 K8s 資源。

2. 設計

該方案的核心在于配置管理的設計,將操作流程配置化,自上而下有如下概念:

  • Service:Modules 或 Tasks 的編排;

  • Module:一種任務場景,是操作單元的集合(其中包含 templates/ 目錄,表征模板文件的集合,可用來配置 K8s 原生資源);
     

  • Task:操作單元,使用 plugin 及參數執行操作;
     

  • Plugin:操作指令,類似開發語言中的函數。

抽象目標場景中的通用操作,這些通用操作即為可在 yaml 中使用的原語,對應上述 Plugin:

  • K8s 相關

    • CreateNamespace

    • DeleteNamespace

    • PrepareSecret

    • PrepareConfigMap

    • PrepareBatchDeployments

    • WaitForBatchDeploymentsReady

    • etc.

  • 觀測性相關

    • DeploymentCreationEfficiency

    • PodCreationEfficiency

    • etc.

  • 檢測項相關

    • CheckPodAnnotations

    • CheckPodObjectInfo

    • CheckPodInnerStates

    • etc.

  • 控制語句相關

    • RepeatNTimes

    • etc.

上述 4 個概念的關系如下:

3.png

示例可參見文章開頭的 yaml 文件,對應形式二。

3. 核心實現

CRD 設計:

package v1alpha1import (
    corev1 "k8s.io/api/core/v1"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1")// BeidouType is the type related to Beidou execution.type BeidouType string

const (// BeidouTask represents the Task execution type.BeidouTask BeidouType = "Task")// +genclient// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// Beidou represents a crd used to describe serices.type Beidou struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`

    Spec   BeidouSpec   `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
    Status BeidouStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}// BeidouSpec is the spec of a Beidou.type BeidouSpec struct {
    Steps      []BeidouStep      `json:"steps" protobuf:"bytes,1,opt,name=steps"`
    References []BeidouReference `json:"references" protobuf:"bytes,2,opt,name=references"`
}// BeidouStep is the spec of step.type BeidouStep struct {
    Name       string            `json:"name" protobuf:"bytes,1,opt,name=name"`
    Operations []BeidouOperation `json:"operations" protobuf:"bytes,2,opt,name=operations"`
}// BeidouOperation is the spec of operation.type BeidouOperation struct {
    Name string      `json:"name" protobuf:"bytes,1,opt,name=name"`
    Type BeidouType  `json:"type" protobuf:"bytes,2,opt,name=type"`
    Op   string      `json:"op" protobuf:"bytes,3,opt,name=op"`
    Args []BeidouArg `json:"args" protobuf:"bytes,4,opt,name=args"`
}// BeidouArg is the spec of arg.type BeidouArg struct {
    Name        string                   `json:"name" protobuf:"bytes,1,opt,name=name"`
    Value       string                   `json:"value,omitempty" protobuf:"bytes,2,opt,name=value"`
    Reference   BeidouOperationReference `json:"reference,omitempty" protobuf:"bytes,3,opt,name=reference"`
    Tolerations []corev1.Toleration      `json:"tolerations,omitempty" protobuf:"bytes,4,opt,name=tolerations"`
    Checking    []string                 `json:"checking,omitempty" protobuf:"bytes,5,opt,name=checking"`
}// BeidouOperationReference is the spec of operation reference.type BeidouOperationReference struct {
    ID string `json:"id" protobuf:"bytes,1,opt,name=id"`
}// BeidouReference is the spec of reference.type BeidouReference struct {
    ID    string       `json:"id" protobuf:"bytes,1,opt,name=id"`
    Steps []BeidouStep `json:"steps" protobuf:"bytes,2,opt,name=steps"`
}// BeidouStatus represents the current state of a Beidou.type BeidouStatus struct {
    Message string `json:"message" protobuf:"bytes,1,opt,name=message"`
}// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object// BeidouList is a collection of Beidou.type BeidouList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata" protobuf:"bytes,1,opt,name=metadata"`

    Items []Beidou `json:"items" protobuf:"bytes,2,opt,name=items"`
}

核心流程:

// ExecSteps executes steps.func ExecSteps(ctx context.Context, steps []v1alpha1.BeidouStep, references []v1alpha1.BeidouReference) error {
    logger, _ := ctx.Value(CtxLogger).(*log.Entry)var hasMonitored boolfor i, step := range steps {for j, op := range step.Operations {switch op.Op {case "DeploymentCreationEfficiency":if !hasMonitored {defer func() {
                        err := monitor.Output()if err != nil {
                            logger.Errorf("Failed to output: %s", err)
                        }
                    }()
                }
                hasMonitored = true}

            err := ExecOperation(ctx, op, references)if err != nil {return fmt.Errorf("failed to run operation %s: %s", op.Name, err)
            }
        }
    }return nil}// ExecOperation executes operation.func ExecOperation(ctx context.Context, op v1alpha1.BeidouOperation, references []v1alpha1.BeidouReference) error {switch op.Type {case v1alpha1.BeidouTask:if !tasks.IsRegistered(op.Op) {return ErrNotRegistered
        }if !tasks.DoesSupportReference(op.Op) {return ExecTask(ctx, op.Op, op.Args)
        }return ExecTaskWithRefer(ctx, op.Op, op.Args, references)
    }return nil}// ExecTask executes a task.func ExecTask(ctx context.Context, opname string, args []v1alpha1.BeidouArg) error {switch opname {case tasks.CreateNamespace:var ns stringfor _, arg := range args {switch arg.Name {case "NS":
                ns = arg.Value
            }
        }return op.CreateNamespace(ctx, ns)// ...}// ...}// ExecTaskWithRefer executes a task with reference.func ExecTaskWithRefer(ctx context.Context, opname string, args []v1alpha1.BeidouArg, references []v1alpha1.BeidouReference) error {switch opname {case tasks.RepeatNTimes:var times intvar steps []v1alpha1.BeidouStepvar err errorfor _, arg := range args {switch arg.Name {case "TIMES":
                times, err = strconv.Atoi(arg.Value)if err != nil {return ErrParseArgs
                }case "ACTION":for _, refer := range references {if refer.ID == arg.Reference.ID {
                        steps = refer.Stepsbreak}
                }
            }
        }return RepeatNTimes(ctx, times, steps)
    }return ErrNotImplemented
}

操作原語的實現示例:

// PodAnnotations is an operation used to check whether annotations of Pod are expected.func PodAnnotations(ctx context.Context, data PodAnnotationsData) error {kclient, ok := ctx.Value(tasks.KubernetesClient).(kubernetes.Interface)if !ok {return tasks.ErrNoKubernetesClient}pods, err := kclient.CoreV1().Pods(data.Namespace).List(metav1.ListOptions{})if err != nil {
        return fmt.Errorf("failed to list pods in ns %s: %s", data.Namespace, err)}

    for _, pod := range pods.Items {if pod.Annotations == nil {
            return fmt.Errorf("pod %s in ns %s has no annotations", pod.Name, data.Namespace)}

        for _, annotation := range data.Exists {if _, exists := pod.Annotations[annotation]; !exists {return fmt.Errorf("annotation %s does not exist in pod %s in ns %s", annotation, pod.Name, data.Namespace)
            }}

        for k, v := range data.Equal {if pod.Annotations[k] != v {return fmt.Errorf("value of annotation %s is not %s in pod %s in ns %s", k, v, pod.Name, data.Namespace)
            }}
    }

    return nil
}

以上就是Kubernetes如何在yaml中編程,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

凤庆县| 龙海市| 揭东县| 眉山市| 宜兰市| 靖西县| 扎鲁特旗| 巴林左旗| 罗定市| 昌平区| 庆云县| 泾川县| 饶河县| 桃江县| 阿瓦提县| 通州市| 宁陕县| 尼勒克县| 台州市| 田阳县| 永川市| 阳江市| 剑川县| 贞丰县| 腾冲县| 佛冈县| 广州市| 遂川县| 琼中| 扶风县| 临桂县| 法库县| 曲阳县| 洛扎县| 沁源县| 古浪县| 永州市| 东丽区| 新乡县| 施甸县| 承德市|