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