在写本文的时候,Kubernetes已经有6年左右的历史了,在过去两年中,Kubernetes的知名度不断上升,成为工程师最爱的平台之一。今年,它被列为最受欢迎的平台的第三位。如果你还没听说过Kubernetes的话,那么它是一个允许你运行容器和协调容器负载的平台。
容器最初是作为Linux内核进程隔离的产物,包含了2007就支持的cgroups和2002年就支持的命名空间。2008年,当LXC可用时,容器变得更加重要了,Google开发了“Borg” 好城市 "在容器中运行一切 "的机制。很快来到2013年,Docker发布了,彻底普及了容器。在当时,Mesos是调度容器的主要工具,然而,它并没有那么广泛流行起来。Kubernetes于2015年发布,并迅速成为事实上的容器调度标准。
为了试图理解Kubernetes的普及,让我们考虑一些问题。上一次开发者们能够就部署应用的方式达成一致是什么时候?你知道有多少开发人员按开箱即用的方式运行工具?现在有多少云运维工程师不了解应用程序是如何工作的?我们将在这篇文章中探讨这些问题的答案。
从Puppet和Chef的世界里走出来,Kubernetes的一个重要转变是,从以代码为基础的基础架构转向了以数据为基础的基础架构—具体来说,就是YAML。Kubernetes中的所有资源,包括Pod、Configurations、Deployments、Volumes等,都可以简单地用YAML文件来表达。比如。
apiVersion: v1
kind: Pod
metadata:
name: site
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
这种表示方式使DevOps或SRE工程师更容易完全表达工作负载,而不需要在Python、Ruby或Javascript等语言中用代码表示。
将基础架构作为数据的好处还包括。
GitOps或Git操作版本控制。使用这种方法,你可以将所有的Kubernetes YAML文件都保存在git仓库下,这样你就可以准确地知道何时进行了更改,谁做了更改,以及具体更改了什么。这使得整个组织的透明度更高,并且通过避免团队成员弄不清楚去哪里寻找配置,从而提高了效率。同时,只需合并一个拉动请求,就可以更方便地自动化更改Kubernetes资源。
可扩展性。将资源定义为YAML,使得集群操作人员在Kubernetes资源中改变一两个数字来扩容或者缩容集群。Kubernetes有水平pod自动缩放器,可以指定给定部署所需要的最小和最大pod数量,以便能自动缩容/扩容应对流量低谷/高峰。例如,如果你正在运行的部署可能因为流量突增而需要更多的容量,你可以将maxReplicas从10个改为20个。
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: myapp
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp-deployment
minReplicas: 1
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
安全和控制。YAML是验证在Kubernetes中部署什么和如何部署的好方法。例如,当涉及到安全问题时,一个重要的关注点就是你的工作负载是否以非root用户的身份运行。我们可以利用像conftest这样的工具(YAML/JSON验证器),再加上Open Policy Agent这样的策略验证器,来检查你的工作负载的SecurityContext是否不允许容器作为root用户运行。为此,用户可以使用一个简单的Open Policy Agent rego策略,如下。
package main
deny[msg] {
input.kind = "Deployment"
not input.spec.template.spec.securityContext.runAsNonRoot = true
msg = "Containers must not run as root"
}
云供应商的整合。科技行业的主要趋势之一就是在公有云供应商中运行工作负载。在云供应商组件的帮助下,Kubernetes允许每个集群与它所运行的云供应商进行集成。例如,如果用户在AWS中的Kubernetes中运行某应用程序,并希望该应用程序可以通过服务访问,云供应商会帮助自动创建一个LoadBalancer服务,该服务会自动提供一个Amazon Elastic Load Balancer来将流量转发到应用程序的pods。
Kubernetes的可扩展性很强,开发者很喜欢这一点。Kubernetes已经内置了很多资源,如Pods、Deployments、StatefulSets、Secrets、ConfigMaps等。然而用户和开发者可以通过自定义资源定义的形式添加更多的资源。例如,如果我们想定义一个CronTab资源,我们可以这样做。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.my.org
spec:
group: my.org
versions:
- name: v1
served: true
storage: true
Schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
replicas:
type: integer
minimum: 1
maximum: 10
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
我们以后可以用如下的方式创建一个CronTab资源。
apiVersion: "my.org/v1"
kind: CronTab
metadata:
name: my-cron-object
spec:
cronSpec: "* * * * */5"
image: my-cron-image
replicas: 5
Kubernetes可扩展性的另一种形式是开发者可以编写自己的Operator,这是一个在Kubernetes集群中运行的特定进程,遵循控制循环模式。一个Operator允许用户通过与Kubernetes API对话来自动管理CRD(自定义资源定义)。
社区有几个工具,允许开发者创建自己的Operator。其中一个工具是Operator Framework及其Operator SDK。该SDK为开发者提供了一个框架,让他们可以非常快速地开始创建Operator。例如,您可以通过以下命令行开始创建Operator。
$ operator-sdk new my-operator --repo github.com/myuser/my-operator
这就为你的Operator创建了包括YAML文件和Golang代码在内的整个样板。
.
|____cmd
| |____manager
| | |____main.go
|____go.mod
|____deploy
| |____role.yaml
| |____role_binding.yaml
| |____service_account.yaml
| |____operator.yaml
|____tools.go
|____go.sum
|____.gitignore
|____version
| |____version.go
|____build
| |____bin
| | |____user_setup
| | |____entrypoint
| |____Dockerfile
|____pkg
| |____apis
| | |____apis.go
| |____controller
| | |____controller.go
添加API和控制器的方式如下。
$ operator-sdk add api --api-version=myapp.com/v1alpha1 --kind=MyAppService
$ operator-sdk add controller --api-version=myapp.com/v1alpha1 --kind=MyAppService
最后构建并推送Operator到你的容器注册表中。
$ operator-sdk build your.container.registry/youruser/myapp-operator
如果开发者需要更多的控制权,他们可以修改Golang文件中的样板代码。例如,要修改控制器的具体内容,他们可以对controller.go文件进行修改。
另一个项目,KUDO,只需使用声明式的YAML文件就可以创建Operator。例如,Apache Kafka的Operator就是这样定义的,它允许用户在Kubernetes上面安装一个Kafka集群,只需要几条命令就可以了。
$ kubectl kudo install zookeeper
$ kubectl kudo install kafka
然后用另一个命令来调整kafka参数。
$ kubectl kudo install kafka --instance=my-kafka-name \
-p ZOOKEEPER_URI=zk-zookeeper-0.zk-hs:2181 \
-p ZOOKEEPER_PATH=/my-path -p BROKER_CPUS=3000m \
-p BROKER_COUNT=5 -p BROKER_MEM=4096m \
-p DISK_SIZE=40Gi -p MIN_INSYNC_REPLICAS=3 \
-p NUM_NETWORK_THREADS=10 -p NUM_IO_THREADS=20
在过去的几年里,Kubernetes每隔三四个月就会有一次大版本发布,也就是说,每年都会有三四个大的版本。新功能的引入速度并没有放缓,上一次发布的版本就有超过30种不同的新增功能和改进。此外,即使在困难时期,代码贡献也没有放缓的迹象,正如Kubernetes项目Github的活动所示。
新功能让集群运维人员在面对各种不同的工作负载时有了更多的灵活性。软件工程师也喜欢有更多的控制权,可以直接将应用部署到生产环境中。
Kubernetes受欢迎的另一大方面是其强大的社区。对于初学者来说,Kubernetes在2015年进入1.0版本的时候,就被捐给了云原生计算基金会(CNCF)。
此外,随着项目的推进,还有大量的社区SIG(特殊兴趣小组),它们针对Kubernetes的不同领域进行研究。他们不断地添加新的功能,以方便其他用户使用。
云原生基金会还组织了CloudNativeCon/KubeCon,截止到本文写作时,它是有史以来最大的开源活动。该活动一般每年举办三次,聚集了数千名相关技术专家和专业人士。
此外,云原生基金会有一个技术监督委员会,该委员会和它的SIGs一起研究基金会在云原生生态系统中的新项目和现有项目。这些项目大多有助于提升Kubernetes的价值。
最后,我相信,如果没有社区有意识地互相包容、欢迎任何新人的加入,Kubernetes就不会有今天的成功。
开发人员在未来面临的主要挑战之一是如何更多地关注代码的细节,而不是代码运行的基础设施。为此,无服务器架构正在成为解决这一挑战的主要架构范式之一。已经有一些非常先进的框架,比如Knative和OpenFaas,使用Kubernetes将基础架构从开发者那里抽象出来。
在这篇文章中,我们已经展示了Kubernetes的简单介绍,但这只是冰山一角。用户可以利用更多的资源、功能和配置。我们将继续看到新的开源项目和技术来增强或发展Kubernetes,正如我们提到的那样,这些贡献和社区无处不在。
原文链接:https://stackoverflow.blog/2020/05/29/why-kubernetes-getting-so-popular/
参考阅读:
用代码来说明,为什么需要面向扩展的设计
code review 的几条规则
整洁架构的正确之路
理想的DevOps流程怎么做?看看Slack的代码部署实践
为什么我不赞成在代码中写注释:谈写注释的几种境界
Pull Request 的艺术
本文由高可用架构翻译,技术原创及架构实践文章,欢迎通过公众号菜单「联系我们」进行投稿。
高可用架构
改变互联网的构建方式
长按二维码 关注「高可用架构」公众号