运行应用程序通常需要使用服务器。然而,传统的服务器模式存在一些限制,无法有效定义和强制执行应用程序的边界,也无法确保资源利用的公平性,导致资源利用率低下。
为了克服这些问题,虚拟化技术应运而生。虚拟化技术允许在一台物理服务器上创建多个虚拟机(VM)。
虚拟机(VM)是由软件管理的虚拟化计算机系统的实例,也被称为hypervisor。每个虚拟机都是独立且隔离的实体,拥有自己的虚拟资源。多个虚拟机可以共存于同一台物理服务器上,这样就提高了资源利用率。每个虚拟机都是完全隔离的,并且有自己的操作系统。虚拟化技术有一些限制,其中之一是每台物理系统可以承载的虚拟机数量的限制。
虚拟机和容器
与虚拟机相比,容器提供了一种轻量级的虚拟化解决方案,因为在托管物理系统上运行的多个容器共享操作系统。与虚拟机类似,每个容器都有自己的资源集,包括CPU共享,但它与其他容器共享操作系统。Docker是广泛用于管理容器的容器运行时。
与虚拟机相比,容器具有多个优点,并且被广泛用于打包应用程序。然而,在生产环境中管理容器并提供容错和负载均衡等服务是一项具有挑战性的任务。
这就是Kubernetes发挥作用的地方。它是一个开源且可扩展的容器编排平台。该项目由Google于2014年开源。它自动化容器化应用程序的部署、扩展和管理。Kubernetes允许管理和协调跨多个主机的容器集群,提供容错性和可伸缩性等服务。
注意:Kubernetes通常被称为K8s,因为在“K”和“s”之间有八个字母。
1 架构和组件
一个Kubernetes部署被称为一个Kubernetes集群,具有两种类型的资源:控制平面和节点。每个集群都有一个工作节点池,在Pod上运行容器化应用程序,Pod代表一个或多个共存的容器。这些节点由控制平面管理,如下图所示。在生产环境中,集群将包含多个工作节点,控制平面将在多台机器上运行,确保高可用性和容错性。
1.1 控制平面组件
控制平面的主要组件如下所述:
- etcd:这是用于存储Kubernetes集群数据、服务发现详细信息和API对象的键值存储。
- kube-scheduler:它在工作节点上调度新创建的Pod。
- kube-controller-manager:它运行控制器进程,如处理节点故障的节点控制器和作业控制器。云集成有一个单独的控制器组件。
- kube-apiserver:Kubernetes API服务器是集群的主要管理实体,接收所有REST请求。
Kubernetes架构
1.2 节点组件
Kubernetes集群中的每个工作节点都会运行一些组件。这里选择了Docker作为容器运行时,但Kubernetes还支持其他多种运行时。以下是这些运行时的高级概述:
- Kubelet:它管理Pod中的容器,并确保它们运行并保持健康状态。
- Kube-proxy:它允许来自互联网或集群内部的Pod之间进行网络通信。
2 关键概念
熟悉一些与Kubernetes相关的关键概念:
- Pods:Kubernetes的基本构建块。Pod是Kubernetes中最小的可部署单位,代表一个或多个共存的容器。
- ReplicaSets:确保始终运行指定数量的Pod副本。通常,我们不直接管理ReplicaSets,而是使用高级概念Deployments。
- Deployments:一个更高级的抽象,用于管理ReplicaSets。Deployments允许我们以声明方式定义和更新应用程序的期望状态。
- Services:同一主机上的Pod可以与其他Pod进行通信。但是,如果我们希望将运行在Pod上的应用程序暴露给外部世界(或集群内部),我们可以使用Service API。Service允许我们抽象出底层的Pod IP,并提供诸如负载均衡之类的服务。
- 命名空间:提供一种逻辑上划分集群资源的方式,因此,命名空间内的资源名称需要是唯一的。
3 部署示例应用程序
本节将在minikube上部署一个示例应用程序,minikube是一个本地的Kubernetes集群。开发人员需要遵循minikube网站上提到的步骤,在本地系统上安装minikube。然后,使用以下命令启动集群:
minikube start
要与Kubernetes集群交互,可以使用kubectl命令行工具使用Kubernetes API对集群进行各种操作。请按照Kubernetes网站上提供的说明安装kubectl CLI。或者,minikube也附带了kubectl,可以使用minikube kubectl -- [commands]来访问。本文假设已经安装了kubectl。
kubectl命令的一般结构是提供要在<resource>上执行的<action>。要获取节点列表,可以使用以下命令。这里还提供了一些其他常见示例,以帮助开发人员入门。请注意,通过在命令的末尾添加--help,可以获取有关其用法的更多信息。
kubectl get nodes
kubectl get nodes --help
kubectl get pods
kubectl describe pods nginx-pod
3.1 创建一个Pod
实际上,这里不会直接创建Pods,而是使用工作负载资源(例如Deployments)来创建它们。不过,为了帮助入门,以下是创建Pod的YAML模板:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.25.1
ports:
- containerPort: 80
上面显示的YAML文件更容易理解。将Pod命名为nginx-pod,并指定它包含一个运行nginx的单个容器。重申一下,Pods是Kubernetes的基本构建块。Pod是Kubernetes中最小的可部署单元,最常见的用例是每个Pod运行一个单独的容器的模型。
kubectl可以以两种不同的方式使用:命令式或声明式。在声明式使用时,提供一个描述所需状态的清单,例如上面显示的YAML文件,并且kubectl将其提交给集群,确定如何实现它。另一方面,在命令式使用时,提供特定于集群的命令来指示kubectl要执行的操作。
要创建上述文件中显示的Pod,请将内容保存到名为nginx-pod的文件中,然后使用以下命令运行kubectl apply:
kubectl apply -f nginx-pod.yaml
kubectl get pods
Pod的状态从ContainerCreating更改为Running可能需要几秒钟的时间。在READY列中应该能够看到1/1。
第二个命令获取Pod列表,如果一切顺利,会在列表中找到Pod。
图片
至此已经在Kubernetes上创建了第一个Pod!
可以看到Pod正在运行一个监听端口80的nginx容器。然而,无法通过http://127.0.0.1:80访问它。这是可以理解的,Pod在集群内部运行,默认情况下无法直接访问。
通常,不会直接访问Pods,但是为了帮助入门,可以使用kubectl的port-forward功能,它可以在主机和Pod上指定端口之间建立隧道。
kubectl port-forward nginx-pod 8080:80
运行以上命令后,在浏览器中浏览到http://127.0.0.1:8080,应该能够看到nginx服务器的欢迎页面。按下“Ctrl + C”结束端口转发会话。现在可以删除这个Pod,因为将通过创建Deployments来管理它们。
kubectl delete pod nginx-pod
kubectl get pods
3.2 创建一个部署
在前面的部分中,创建了第一个Pod,但在实践中,通常不直接创建Pod,而是使用工作负载资源,如Deployments。在本部分中,将使用下面的清单创建第一个Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.25.1
ports:
- containerPort: 80
该清单有三个重要部分。将部署命名为nginx-deployment,然后通过指定副本数为2创建一个ReplicaSet。之前学到过,ReplicaSets确保指定数量的Pod副本始终运行。部署名称将指导副本的命名,稍后会看到。最后,在第12-21行中指定Pods模板。这是一个示例,重申下通常不直接创建Pods,而是使用更高级的概念(如Deployments)管理它们。
将清单保存到名为nginx-deployment.yaml的文件中,然后使用以下命令创建一个部署:
kubectl apply -f nginx-deployment.yaml
kubectl get deployments
如果一切顺利,应该能够在列表中看到部署。可以注意到READY列中的2/2与ReplicaSet规范相匹配。还可以获取Pod列表来确认这一点。
现在,可以通过删除Pods来测试部署的可用性,并观察它如何通过启动新的Pods自动实现期望的状态。需要使用以下命令:
kubectl get pods
kubectl delete pod nginx-deployment-7d6955794c-s8c2h
kubectl get pods
被删除的Pod的名称对您来说可能会有所不同,但是您会注意到一旦删除一个Pod,就会实例化另一个具有不同名称的Pod。可以观察AGE列来确认这种行为。
现在已经成功创建了第一个部署!
3.3 创建一个服务
开发人员可以使用服务API将运行在Pods上的应用程序暴露给外部世界。服务允许我们抽象底层的Pod IP,并提供负载均衡等服务。通常,可以创建多种类型的服务,并存在许多相关的用例。可以使用以下命令为部署创建一个服务:
kubectl expose deployment nginx-deployment --type=LoadBalancer --name=nginx-service --port=80
kubectl expose允许将Kubernetes对象(在我们的情况下是部署)作为新的Kubernetes服务暴露出来。可以在服务列表中看到新创建的服务,并使用describe命令获取有关服务的更多详细信息,如下所示:
kubectl get services
kubectl describe service nginx-service
NodePort字段的值指定了一个随机端口,可以用于访问服务。由于在本文中使用minikube,可以使用以下命令访问服务:
minikube service nginx-service
这将打开nginx的欢迎页面。但是,我们不直接访问Pods,可以通过删除现有的Pods并重新访问服务来确认这一行为。
4 总结
Kubernetes是一个开源的、可扩展的容器编排平台。Kubernetes允许管理和协调跨多个主机的容器集群,提供容错和可扩展性等服务。
本文详细介绍了Kubernetes的架构和组件,结合了各种关键概念的简介。本文提供了一个实践指南,介绍了如何在本地的Kubernetes集群minikube上部署样例应用程序。