久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

KubeVela是如何將appfile轉換為K8s特定資源對象的

162次閱讀
沒有評論

共計 10871 個字符,預計需要花費 28 分鐘才能閱讀完成。

這期內容當中丸趣 TV 小編將會給大家?guī)碛嘘P KubeVela 是如何將 appfile 轉換為 K8s 特定資源對象的,文章內容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

KubeVela 是一個簡單易用又高度可擴展的云原生應用管理引擎,是基于 Kubernetes 及阿里云與微軟云共同發(fā)布的云原生應用開發(fā)模型 OAM 構建。

KubeVela 基于 OAM 模型構建了一套具體的實現,通過 Golang 編寫,可以端到端地為用戶構建云原生應用的平臺,提供一個相對完整的解決方案。

下面主要目的是探索 KubeVela  如何將一個  appfile  文件轉換為 K8s 中特定的資源對象。

該過程總的來說分為兩個階段:

appfile  轉為 K8s 中的  application

application  轉換為對應的 K8s 資源對象

# vela.yaml
name: test
services:
 nginx:
 type: webservice
 image: nginx
 env:
 - name: NAME
 value: kubevela
 # svc trait
 svc:
 type: NodePort
 ports:
 - port: 80
 nodePort: 32017

利用 vela up 命令可以完成部署。

vela up 命令

建議:在看 vela 命令行工具代碼之前,先去簡單了解一下 cobra 框架。

// references/cli/up.go
// NewUpCommand will create command for applying an AppFile
func NewUpCommand(c types.Args, ioStream cmdutil.IOStreams) *cobra.Command {
 cmd :=  cobra.Command{
 Use:  up ,
 DisableFlagsInUseLine: true,
 Short:  Apply an appfile ,
 Long:  Apply an appfile ,
 Annotations: map[string]string{
 types.TagCommandType: types.TypeStart,
 },
 PersistentPreRunE: func(cmd *cobra.Command, args []string) error { return c.SetConfig()
 },
 RunE: func(cmd *cobra.Command, args []string) error { velaEnv, err := GetEnv(cmd)
 if err != nil {
 return err
 }
 kubecli, err := c.GetClient()
 if err != nil {
 return err
 }
 o :=  common.AppfileOptions{
 Kubecli: kubecli,
 IO: ioStream,
 Env: velaEnv,
 }
 filePath, err := cmd.Flags().GetString(appFilePath)
 if err != nil {
 return err
 }
 return o.Run(filePath, velaEnv.Namespace, c)
 },
 }
 cmd.SetOut(ioStream.Out)
 cmd.Flags().StringP(appFilePath,  f ,  ,  specify file path for appfile)
 return cmd
}

上面源碼展示的是 vela up 命令的入口。

在 PresistentPreRunE 函數中,通過調用 c.SetConfig() 完成 Kuberentes 配置信息 kubeconfig 的注入。

在 RunE 函數中:

首先,獲取 vela 的 env 變量,velaEnv.Namespace 對應 Kubernetes 的命名空間。

其次,獲取 Kubernetes 的客戶端,kubectl。

接著,利用 Kubernetes 客戶端和 vleaEnv 來構建渲染 Appfile 需要的 AppfileOptions。

最后,調用 o.Run(filePath, velaEnv.Namespace, c)。

filePath: appfile 的路徑

velaEnv.Namespace:對應 K8s 的 namespace

c:K8s 客戶端

該函數需要三個參數,其中 filePath 用于指定 appfile 的位置,velaEnv.Namespace 和 c 用來將渲染后的 Application 創(chuàng)建到指定命名空間。

如何將一個 appfile 轉為 Kubernetes 中的 Application

起點:appfile

終點:applicatioin

路徑:appfile – application (services – component)

comp[workload, traits]1. 起點:AppFile

// references/appfile/api/appfile.go
// AppFile defines the spec of KubeVela Appfile
type AppFile struct {
 Name string `json: name `
 CreateTime time.Time `json: createTime,omitempty `
 UpdateTime time.Time `json: updateTime,omitempty `
 Services map[string]Service `json: services `
 Secrets map[string]string `json: secrets,omitempty `
 configGetter config.Store
 initialized bool
// NewAppFile init an empty AppFile struct
func NewAppFile() *AppFile {
 return  AppFile{ Services: make(map[string]Service),
 Secrets: make(map[string]string),
 configGetter:  config.Local{},
 }
}
// references/appfile/api/service.go
// Service defines the service spec for AppFile, it will contain all related information including OAM component, traits, source to image, etc...
type Service map[string]interface{}

上面兩段代碼是 AppFile 在客戶端的聲明,vela 會將指定路徑的 yaml 文件讀取后,賦值給一個 AppFile。

// references/appfile/api/appfile.go
// LoadFromFile will read the file and load the AppFile struct
func LoadFromFile(filename string) (*AppFile, error) { b, err := ioutil.ReadFile(filepath.Clean(filename))
 if err != nil {
 return nil, err
 }
 af := NewAppFile()
 // Add JSON format appfile support
 ext := filepath.Ext(filename)
 switch ext {
 case  .yaml ,  .yml :
 err = yaml.Unmarshal(b, af)
 case  .json :
 af, err = JSONToYaml(b, af)
 default:
 if json.Valid(b) { af, err = JSONToYaml(b, af)
 } else { err = yaml.Unmarshal(b, af)
 }
 }
 if err != nil {
 return nil, err
 }
 return af, nil
}

下面為讀取 vela.yaml 文件后,加載到 AppFile 中的數據:

# vela.yaml
name: test
services:
 nginx:
 type: webservice
 image: nginx
 env:
 - name: NAME
 value: kubevela
 # svc trait
 svc:
 type: NodePort
 ports:
 - port: 80
 nodePort: 32017
Name: test
CreateTime: 0001-01-01 00:00:00 +0000 UTC
UpdateTime: 0001-01-01 00:00:00 +0000 UTC
Services: map[
 nginx: map[ env: [map[name: NAME value: kubevela]] 
 image: nginx 
 svc: map[ports: [map[nodePort: 32017 port: 80]] type: NodePort] 
 type: webservice
 ]
 ]
Secrets map[]
configGetter: 0x447abd0 
initialized: false

2. 終點:application

// apis/core.oam.dev/application_types.go
type Application struct {
 metav1.TypeMeta `json: ,inline `
 metav1.ObjectMeta `json: metadata,omitempty `
 Spec ApplicationSpec `json: spec,omitempty `
 Status AppStatus `json: status,omitempty `
// ApplicationSpec is the spec of Application
type ApplicationSpec struct { Components []ApplicationComponent `json: components `
 // TODO(wonderflow): we should have application level scopes supported here
 // RolloutPlan is the details on how to rollout the resources
 // The controller simply replace the old resources with the new one if there is no rollout plan involved
 // +optional
 RolloutPlan *v1alpha1.RolloutPlan `json: rolloutPlan,omitempty `
}

上面代碼,為 Application 的聲明,結合 .vela/deploy.yaml(見下面代碼),可以看出,要將一個 AppFile 渲染為 Application 主要就是將 AppFile 的 Services 轉化為 Application 的 Components。

# .vela/deploy.yaml
apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
 creationTimestamp: null
 name: test
 namespace: default
spec:
 components:
 - name: nginx
 scopes:
 healthscopes.core.oam.dev: test-default-health
 settings:
 env:
 - name: NAME
 value: kubevela
 image: nginx
 traits:
 - name: svc
 properties:
 ports:
 - nodePort: 32017
 port: 80
 type: NodePort
 type: webservice
status: {}

3. 路徑:Services – Components

結合以上內容可以看出,將 Appfile 轉化為 Application 主要是將 Services 渲染為 Components。

// references/appfile/api/appfile.go
// BuildOAMApplication renders Appfile into Application, Scopes and other K8s Resources.
func (app *AppFile) BuildOAMApplication(env *types.EnvMeta, io cmdutil.IOStreams, tm template.Manager, silence bool) (*v1alpha2.Application, []oam.Object, error) {
 ...
 servApp := new(v1alpha2.Application)
 servApp.SetNamespace(env.Namespace)
 servApp.SetName(app.Name)
 servApp.Spec.Components = []v1alpha2.ApplicationComponent{}
 for serviceName, svc := range app.GetServices() {
 ...
 //  完成  Service  到  Component  的轉化
 comp, err := svc.RenderServiceToApplicationComponent(tm, serviceName)
 if err != nil {
 return nil, nil, err
 }
 servApp.Spec.Components = append(servApp.Spec.Components, comp)
 }
 servApp.SetGroupVersionKind(v1alpha2.SchemeGroupVersion.WithKind( Application))
 auxiliaryObjects = append(auxiliaryObjects, addDefaultHealthScopeToApplication(servApp))
 return servApp, auxiliaryObjects, nil
}

上面的代碼是 vela 將 Appfile 轉化為 Application 代碼實現的位置。其中 comp, err := svc.RenderServiceToApplicationComponent(tm, serviceName) 完成 Service 到 Component 的轉化。

// references/appfile/api/service.go
// RenderServiceToApplicationComponent render all capabilities of a service to CUE values to KubeVela Application.
func (s Service) RenderServiceToApplicationComponent(tm template.Manager, serviceName string) (v1alpha2.ApplicationComponent, error) {
 // sort out configs by workload/trait
 workloadKeys := map[string]interface{}{}
 var traits []v1alpha2.ApplicationTrait
 wtype := s.GetType()
 comp := v1alpha2.ApplicationComponent{
 Name: serviceName,
 WorkloadType: wtype,
 }
 for k, v := range s.GetApplicationConfig() {
 //  判斷是否為  trait
 if tm.IsTrait(k) {
 trait := v1alpha2.ApplicationTrait{
 Name: k,
 }
 ....
 //  如果是  triat  加入  traits  中
 traits = append(traits, trait)
 continue
 }
 workloadKeys[k] = v
 }
 // Handle workloadKeys to settings
 settings :=  runtime.RawExte nsion{}
 pt, err := json.Marshal(workloadKeys)
 if err != nil {
 return comp, err
 }
 if err := settings.UnmarshalJSON(pt); err != nil {
 return comp, err
 }
 comp.Settings = *settings
 if len(traits)   0 {
 comp.Traits = traits
 }
 return comp, nil
}

4. 總結

執(zhí)行 vela up 命令,渲染 appfile 為 Application,將數據寫入到 .vela/deploy.yaml 中,并在 K8s 中創(chuàng)建。

Application 是如何轉換為對應 K8s 資源對象

起點:Application

中點:ApplicationConfiguration, Component

終點:Deployment, Service

路徑:

application_controller

applicationconfiguration controller

【建議】了解一下內容:– client-to

controller-runtime

operator

1. Application

#  獲取集群中的  Application
$ kubectl get application
NAMESPACE NAME AGE
default test 24h

2. ApplicationConfiguration 和 Component

當 application controller 獲取到 Application 資源對象之后,會根據其內容創(chuàng)建出對應的 ApplicationConfiguration 和 Component。

#  獲取  ApplicationConfiguration  和  Component
$ kubectl get ApplicationConfiguration,Component
NAME AGE
applicationconfiguration.core.oam.dev/test 24h
NAME WORKLOAD-KIND AGE
component.core.oam.dev/nginx Deployment 24h

ApplicationiConfiguration 中以名字的方式引入 Component:

3. application controller 基本邏輯:

獲取一個 Application 資源對象。

將 Application 資源對象渲染為 ApplicationConfiguration 和 Component。

創(chuàng)建 ApplicationConfiguration 和 Component 資源對象。

代碼:

// pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go
// Reconcile process app event
func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { ctx := context.Background()
 applog := r.Log.WithValues(application , req.NamespacedName)
 
 // 1.  獲取  Application
 app := new(v1alpha2.Application)
 if err := r.Get(ctx, client.ObjectKey{
 Name: req.Name,
 Namespace: req.Namespace,
 }, app); err != nil {
 ...
 }
 ...
 // 2.  將  Application  轉換為  ApplicationConfiguration  和  Component
 handler :=  appHandler{r, app, applog}
 ...
 appParser := appfile.NewApplicationParser(r.Client, r.dm)
 ...
 appfile, err := appParser.GenerateAppFile(ctx, app.Name, app)
 ...
 ac, comps, err := appParser.GenerateApplicationConfiguration(appfile, app.Namespace)
 ...
 
 // 3.  在集群中創(chuàng)建  ApplicationConfiguration  和  Component 
 // apply appConfig   component to the cluster
 if err := handler.apply(ctx, ac, comps); err != nil { applog.Error(err,  [Handle apply] )
 app.Status.SetConditions(errorCondition( Applied , err))
 return handler.handleErr(err)
 }
 ...
 return ctrl.Result{}, r.UpdateStatus(ctx, app)
}

4. applicationconfiguration controller 基本邏輯:

獲取 ApplicationConfiguration 資源對象。

循環(huán)遍歷,獲取每一個 Component 并將 workload 和 trait 渲染為對應的 K8s 資源對象。

創(chuàng)建對應的 K8s 資源對象。

代碼:

// pkg/controller/core.oam.dev/v1alpha2/applicationcinfiguratioin/applicationconfiguratioin.go
// Reconcile an OAM ApplicationConfigurations by rendering and instantiating its
// Components and Traits.
func (r *OAMApplicationReconciler) Reconcile(req reconcile.Request) (reconcile.Result, error) {
 ...
 ac :=  v1alpha2.ApplicationConfiguration{}
 // 1.  獲取  ApplicationConfiguration
 if err := r.client.Get(ctx, req.NamespacedName, ac); err != nil {
 ...
 }
 return r.ACReconcile(ctx, ac, log)
// ACReconcile contains all the reconcile logic of an AC, it can be used by other controller
func (r *OAMApplicationReconciler) ACReconcile(ctx context.Context, ac *v1alpha2.ApplicationConfiguration,
 log logging.Logger) (result reconcile.Result, returnErr error) {
 
 ...
 // 2.  渲染
 //  此處  workloads  包含所有 Component 對應的的  workload  和  tratis  的  k8s  資源對象
 workloads, depStatus, err := r.components.Render(ctx, ac)
 ...
 
 applyOpts := []apply.ApplyOption{apply.MustBeControllableBy(ac.GetUID()), applyOnceOnly(ac, r.applyOnceOnlyMode, log)}
 
 // 3.  創(chuàng)建  workload  和  traits  對應的  k8s  資源對象
 if err := r.workloads.Apply(ctx, ac.Status.Workloads, workloads, applyOpts...); err != nil {
 ...
 }
 
 ...
 // the defer function will do the final status update
 return reconcile.Result{RequeueAfter: waitTime}, nil
}

5. 總結

當 vela up 將一個 AppFile 渲染為一個 Application 后,后續(xù)的流程由 application controller 和 applicationconfiguration controller 完成。

上述就是丸趣 TV 小編為大家分享的 KubeVela 是如何將 appfile 轉換為 K8s 特定資源對象的了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注丸趣 TV 行業(yè)資訊頻道。

正文完
 
丸趣
版權聲明:本站原創(chuàng)文章,由 丸趣 2023-08-16發(fā)表,共計10871字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發(fā)布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 鸡西市| 大关县| 乃东县| 长寿区| 奎屯市| 沁源县| 阿坝| 东宁县| 娄烦县| 玛曲县| 巴青县| 钦州市| 上高县| 历史| 阳朔县| 通化市| 涟源市| 南投市| 上高县| 崇义县| 益阳市| 尼勒克县| 平昌县| 金塔县| 霍林郭勒市| 金坛市| 枣庄市| 湘潭市| 杭州市| 宁都县| 连江县| 确山县| 雅安市| 南郑县| 南投县| 武功县| 富平县| 拉萨市| 石柱| 尉犁县| 博罗县|