在这篇博文中,咱们回忆了Kubernetes办理前端,并讨论了这些东西是怎么被构建的。

译自The Inner Workings of Kubernetes Management Frontends — A Software Engineer’s Perspective,作者是 Christoph Enne 。

近年来Kubernetes的鼓起导致了大量开源的Kubernetes办理东西形似凭空出现。这篇文章背面的研究的目的仅仅是要理解这些东西的架构,而且随后为企图开端自己的Kubernetes前端开发的开发者供给一个扼要的概述和挑选。咱们不会深入探讨这些东西本身以及它们企图处理的问题,而是将重点放在软件工程方面。咱们还仅探究开源和自保管东西,不讨论云供给商的PaaS/IaaS渠道——这将是一篇彻底不同的文章。

搭建和与第一个集群进行交互或许会令人手足无措。就像我相同,你或许遇到了臭名远扬的kubernetes/dashboard,依照装置阐明进行了装置,并问自己:”我刚才做了什么,为什么它的作业办法是这样的?” 在对集群进行一些调整之后,你或许还装置了更多的外部东西来帮助你办理集群的某些详细方面,为你供给CLI或Web UI。

作为最近几年主要从事Web开发的软件工程师,我对这些东西是怎么构建和布置的感到好奇。

咱们首先澄清一下接下来探究不同Kubernetes UI所需的一些基本知识。之后,咱们将看到它们有什么共同之处,以及是什么使这种软件如此特别,最终构成一个主张,阐明怎么自己构建Kubernetes Web UI。

官方文档在任何状况下都非常有帮助;只需求记住一件重要的事情:无论在何时何地与集群进行交互,都是经过Kubernetes API进行的 – 至少就本文的范围而言是如此,虽然或许还有其他用例。

作为该API的顾客,需求知道它保管在哪里以及怎么对其进行身份验证。Kubernetes API能够从集群内部(即从运转在pod上的应用程序)和集群外部(例如从指令行)进行拜访。可是,在某些状况下,API仅可从VPN内拜访。

由于咱们正在查看具有Web UI的东西,因此需求暴露该UI及其后端,以便用户能够拜访它。选项是:

  • 运用kubectl proxy打开从本地机器到集群的署理(拜见 拜访集群),
  • 运用kubectl port-forward将本地端口转发到集群的特定pod(拜见 运用端口转发拜访集群中的应用程序),
  • 运用类型为LoadBalancer的Kubernetes服务来拜访集群的应用程序(拜见 运用服务拜访集群中的应用程序)。

另外,Web服务器也能够在用户的本地机器上运转,在这种状况下就不需求忧虑这些选项。可是,关于这些办法的任何一种办法都需求在用户的机器上有一个有用的kube装备。

办理前端

现在,让咱们看一下一些常用的前端以及它们是怎么构建的。

kubernetes-dashboard

Kubernetes Dashboard是一个盛行的Web UI,用于查看和办理集群中的各种Kubernetes资源。在最新安稳版别2.7中,后端和前端都是同一个容器的一部分。 Go后端一起为API和Angular UI资产供给服务。这种布置战略要求用户运用kubectl proxy来拜访Web应用程序。

在新的3.0版别中,它仍处于alpha阶段,布置战略已更改: 后端和前端每个都在专用的容器中运转。因此,经过kubectl proxy拜访它不复兴效果,由于UI需求拜访在不同pod和端口上运转的后端。应改用此处描绘的端口转发办法。

ArgoCD

ArgoCD是一个Kubernetes的GitOps持续交付东西。它包含几个组件,包含自己的API服务器和Web UI。一切后端组件都是用Go编写的,UI是一个React应用程序。

与Kubernetes Dashboard相同,服务器(包含UI资产)布置在集群内部,这使得用户需求执行端口转发或运用LoadBalancer。这在他们的文档中有描绘。

Lens

Lens是一个桌面UI,但对咱们的探究仍很风趣。它运用Electron、React和Typescript开发。Lens App运用Typescript Kubernetes客户端连接到集群,由于桌面应用程序明显在集群外运转,它运用本地供给的kubeconfig与其连接。

glasskube

是的,一个相当厚颜无耻的插播广告(我在那里作业),但它也是一个风趣的替代方案。关于Glasskube软件包办理器的UI,咱们经过CLI指令在本地启动Web服务器,并从那里供给UI资产。咱们决定采用这种办法,由于在咱们的运用事例中,这更有意义。每逢用户需求Glasskube UI时,他们会根据需求保管它,能够长期或许短期 – 不需求24/7在集群内运转它。

发现

许多开源Kubernetes办理UI的编码办法相似 —— 运用强壮的Kubernetes-go客户端的Go后端,以及JavaScript中的单页面应用程序作为前端。在大多数状况下,Web资源(例如JS文件)与后端一起供给服务,这意味着一个容器一起为后端和前端供给服务。实际上很难找到不是这样构建的东西。

集群内与集群外

当涉及到布置这样一个Web东西时,只有两种挑选:

  • Web服务器布置在集群内的pod上,而且能够经过署理、端口转发或ingress拜访。
  • Web服务器布置在集群外部,直接(本地)布置在用户的机器上。

Kubernetes客户端(例如Go客户端)支撑开发人员这两种办法来连接集群,正如咱们在下面的例子中看到的。

它所依赖的代码段:

这些简化的示例在很大程度上根据这儿和这儿看到的官方示例。

让咱们看一下在集群内部运转应用程序时怎么连接到Kubernetes API:

import (
	"context"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
)
func main() {
	// retreive the config for the cluster we are currently in:
	config, err := rest.InClusterConfig()
	if err != nil {
		panic(err.Error())
	}
	// create the clientset for this config:
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}
	// do something with the clientset, e.g. getting all pods in the cluster:
	// pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
}

Go客户端实现运用pod的服务帐户以及环境变量KUBERNETES_SERVICE_HOSTKUBERNETES_SERVICE_PORT来辨认它所在的集群。随后,它创立REST装备目标,客户端集能够经过该目标取得。

相同,在集群外部运转时,需求创立装备目标,但此装备是从本地kube装备中读取的:

import (
	"context"
	"flag"
	"path/filepath"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/client-go/util/homedir"
)
func main() {
	// get the passed (or default) kube config file path
	var kubeconfig *string
	if home := homedir.HomeDir(); home != "" {
		kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
	} else {
		kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
	}
	flag.Parse()
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err.Error())
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}
	// do something with the clientset, e.g. getting all pods in the cluster:
	// pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
}

相同,Kubernetes Go客户端为咱们供给了一个简略的函数来解析kubeconfig文件以获取装备,然后能够用该装备创立一个clientset。

尝试运转这些简略的示例时,您还会遇到这两种办法之间的一个差异: 运转本地东西更容易,由于您不需求构建映像、将其推送到注册表,然后将其拉入集群。

挑选哪一个?

假定您要以相似的办法构建自己的Kubernetes UI。当涉及到您的东西的Web服务器应该在哪里运转的决定时,有几件事需求考虑:

  • 分发: 在集群内部运转您的东西意味着您有必要构建和分发docker镜像。相反,假如您希望用户在其机器上装置它,则有必要分发本机二进制文件。关于这两种状况,网上都有大量的东西和资源。
  • 可用性: 当您的集群由于某种原因封闭时,用户或许无法拜访保管在集群内部的东西。这带咱们来到下一个关键:
  • 用户入门体验: 这或许是一个边际用例,但本地保管的web东西能够在其一切组件装置在集群之前运用。这意味着您能够为新用户实现某种UI入门流程,使该东西更易于装置和设置。
  • 兼容性: 同一集群的多个用户或许装置了不同版别的您的(本地保管)东西。假如集群内只运转一个web服务器,则无法产生这种状况。
  • 持久性: 当需求存储东西特定的数据(即非Kubernetes资源)时,您能够将其存储在集群内(例如在ConfigMap中)。关于本地布置的变量,您还能够在用户的机器上存储用户特定的数据,如设置。这个决定在很大程度上取决于用例。
  • 开发人员体验: 似乎没有明显的差异,但值得注意的是,在开发集群内web服务器时,在开发期间,这个服务器仍然需求以某种办法支撑集群外装备办法。不然,每次更改后都有必要构建和布置镜像到集群中。

终究,东西是布置在集群内部还是外部彻底取决于您,但始终要考虑用例并意识到运用它的上下文非常重要。您也能够挑选为用户供给这两种选项。

关于咱们在Glasskube,很明显咱们希望为新用户(特别是那些刚接触Kubernetes世界的用户)供给一个易于运用的界面,他们或许还没有设置一切Glasskube集群组件。经过供给保管本地Web服务器的CLI指令和支撑性Web UI,能够支撑这些用户。

总结

在本文中,咱们探究了一些供给Web UI的Kubernetes东西,并从软件工程师的角度剖析了这些东西的Web方面。明显没有一刀切的处理方案来规划和开发这样的东西,但以上列表希望能给出正确方向的提示。像软件工程中的任何事情相同:这取决于。

最终一个插播: 我在Glasskube作业,咱们正在构建缺失的Kubernetes包办理器。假如您对咱们的作业感兴趣,请必须给咱们加星:glasskube/glasskube。咱们也在研究一篇文章,关于不同CLI框架的比较,假如您更倾向指令行。假如这还不够,咱们或许很快会写关于运用htmx的文章,由于它正在盛行,咱们需求您的关注。我现已能看到标题了:”咱们怎么经过运用看似老派的技能来减少95%的代码库” —— 我以为这曾经没有做过;)

本文在云云众生yylives.cc/)首发,欢迎大家拜访。