本文介绍 Kubernetes 集群编排系统的基础知识。
在您的浏览器中运行一个虚拟终端,在浏览器中运行 Minikube,这是一个可在任何地方小规模本地部署的 Kubernetes 集群。不需要安装任何软件或进行任何配置;每个交互性教程都直接从您的网页浏览器上运行。
链接地址:https://kubernetes.io/zh/docs/tutorials/kubernetes-basics/
通过现代的 Web 服务,用户希望应用程序能够 24/7 全天候使用,开发人员希望每天可以多次发布部署新版本的应用程序。 容器化可以帮助软件包达成这些目标,使应用程序能够以简单快速的方式发布和更新,而无需停机。Kubernetes 帮助您确保这些容器化的应用程序在您想要的时间和地点运行,并帮助应用程序找到它们需要的资源和工具。Kubernetes 是一个可用于生产的开源平台,根据 Google 容器集群方面积累的经验,以及来自社区的最佳实践而设计。
Kubernetes 协调一个高可用计算机集群,每个计算机作为独立单元互相连接工作。 Kubernetes 中的抽象允许您将容器化的应用部署到群集,而无需将它们绑定到某个特定的独立计算机。为了使用这种新的部署模型,应用需要以将应用与单个主机分离的方式打包:它们需要被容器化。与过去的那种应用直接以包的方式深度与主机集成的部署模型相比,容器化应用更灵活、更可用。 Kubernetes 以更高效的方式跨群集自动分发和调度应用容器。 Kubernetes 是一个开源平台,并且可应用于生产环境。
一个 Kubernetes 集群包含两种类型的资源:
Master 负责管理整个集群。 Master 协调集群中的所有活动,例如调度应用、维护应用的所需状态、应用扩容以及推出新的更新。
Node 是一个虚拟机或者物理机,它在 Kubernetes 集群中充当工作机器的角色 每个Node都有 Kubelet , 它管理 Node 而且是 Node 与 Master 通信的代理。 Node 还应该具有用于处理容器操作的工具,例如 Docker 或 rkt 。处理生产级流量的 Kubernetes 集群至少应具有三个 Node 。
在 Kubernetes 上部署应用时,您告诉 Master 启动应用容器。 Master 就编排容器在群集的 Node 上运行。 Node 使用 Master 暴露的 Kubernetes API 与 Master 通信。终端用户也可以使用 Kubernetes API 与集群交互。
Kubernetes 既可以部署在物理机上也可以部署在虚拟机上。您可以使用 Minikube 开始部署 Kubernetes 集群。 Minikube 是一种轻量级的 Kubernetes 实现,可在本地计算机上创建 VM 并部署仅包含一个节点的简单集群。 Minikube 可用于 Linux , macOS 和 Windows 系统。Minikube CLI 提供了用于引导群集工作的多种操作,包括启动、停止、查看状态和删除。
既然您已经知道 Kubernetes 是什么,让我们转到在线教程并启动我们的第一个 Kubernetes 集群!
文档链接地址:https://kubernetes.io/zh/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro/
点击如下图的“启动交互教程”按钮
进入如下图页面。此在线终端是一个预配置的Linux环境,它能被用作一个常规的控制台(你可以输入命令)。输入相关命令并点击回车后,在线终端会执行这些命令。
点击“start scenario”按钮,进入如下图页面
在上图右侧终端命令输入区域,输入如下指令,检查minikube是否已被成功安装。
minikube version
执行如下指令,启动集群
minikube start
此时,这个在线终端中已经存在了一个正在运行的Kubernetes集群。Minikube 为我们启动了一个虚拟机,Kubernetes集群正在那个虚拟机中运行。
点击如下图中的“continue”
进入下图页面
执行如下指令,查看kubectl是否已被安装
如上图所示,可以看到kubectl已被成功配置,并且可以看到client、server的版本信息。client版本就是kubectl的版本,server版本为安装在master中的kubernetes版本。
点击上图中的“continue”按钮,进入下图页面
执行如下指令,查看集群的详细信息
kubectl cluster-info
在本教程中,主要是使用如上面的终端命令行来部署和探索我们的应用程序。
执行如下指令,查看集群中的所有节点信息
kubectl get nodes
如上图可以看到,目前只有一个节点,且为Master节点,其状态为Ready,即已经准备好接受部署我们的应用程序。
点击如下图的“继续阅读第二单元”按钮
文档链接地址:https://kubernetes.io/zh/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro/
一旦运行了 Kubernetes 集群,就可以在其上部署容器化应用程序。 为此,您需要创建 Kubernetes Deployment 配置。Deployment 指挥 Kubernetes 如何创建和更新应用程序的实例。创建 Deployment 后,Kubernetes master 将应用程序实例调度到集群中的各个节点上。
创建应用程序实例后,Kubernetes Deployment 控制器会持续监视这些实例。 如果托管实例的节点关闭或被删除,则 Deployment 控制器会将该实例替换为群集中另一个节点上的实例。 这提供了一种自我修复机制来解决机器故障维护问题。
在没有 Kubernetes 这种编排系统之前,安装脚本通常用于启动应用程序,但它们不允许从机器故障中恢复。通过创建应用程序实例并使它们在节点之间运行, Kubernetes Deployments 提供了一种与众不同的应用程序管理方法。
您可以使用 Kubernetes 命令行界面创建和管理 Deployment,Kubectl.Kubectl 使用 Kubernetes API 与集群进行交互。
创建 Deployment 时,您需要指定应用程序的容器映像以及要运行的副本数。
对于我们的第一次部署,我们将使用打包在 Docker 容器中的 Node.js 应用程序。 要创建 Node.js 应用程序并部署 Docker 容器。
点击如下图的“开启交互式教程”按钮
进入如下图页面
下面将讲述使用kubectl在kubernetes集群中部署第一个应用程序,学习kubectlcli的基本知识以及如何与应用程序交互。
点击上图中的“start scenario”按钮,进入如下图页面
和minikube一样,kubectl 也被安装到在线终端。
kubectl 命令的常用格式为kubectl action resource
可以通过在命令后面添加--help,来查看指定命令可能参数的相关信息。
执行如下指令,查看kubectl是否已被正常安装
如上图所示,kubectl已被正常安装,可以看到其client、server版本信息。
执行如下指令,查看集群中的节点信息
kubectl get nodes
点击上图中的“continue”按钮,进入如下图页面
通过执行kubectl create deployment指令来在集群中部署我们的第一个应用。我们需要提供部署名称和应用程序映像位置(包括托管在Docker hub外部的映像的完整存储库url)。
kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
此时,通过创建deployment我们已经部署了我们的第一个应用,集群将会为我们做一些事情:1.在集群中查找一个合适的可以用来运行应用实例的节点。(目前我们只有一个可以使用的Master节点,其状态为Ready)2.在这个节点上编排应用实例运行。3.配置群集以便在需要的时候在新节点重新编排应用实例。
执行如下指令,查看目前的所有部署。
kubectl get deployments
如上图所示,我们可以看到有一个deployment正在运行应用程序的一个实例。这个实例正在节点(本文中只有一个master节点)的Docker容器中运行。
点击上图中的“continue”按钮,进入如下图页面。
运行在Kubernetes内部的pod是运行在一个私有的、孤立的网络上。默认情况下,它们在同一个kubernetes集群内的其他pod和服务中可见,但在该网络之外则不可见。当我们使用kubectl时,我们通过一个API端点与应用程序进行交互。
kubectl命令可以创建一个代理,将通信转发到集群范围内的专用网络。代理可以通过按control-C终止,并且在运行时不会显示任何输出。
下面,我们开启第二个终端窗口来运行代理,执行如下指令:
echo -e "\n\n\n\e[92mStarting Proxy. After starting it will not output a response. Please click the first Terminal Tab\n";
kubectl proxy
我们现在就有了我们的主机(在线终端)和Kubernetes集群的连接。这个代理可以从终端直接访问API。
此时,我们可以通过api使用curl指令直接查询版本信息
curl http://localhost:8001/version
API服务器将根据pod名称为每个pod自动创建一个端点,该端点也可以通过代理访问。
首先,我们需要获取Pod名称,然后将其存储在环境变量POD_NAME中
export POD_NAME=$(kubectl get pods -o go-template --template '{
{range .items}}{
{.metadata.name}}{
{"\n"}}{
{end}}')
echo Name of the Pod: $POD_NAME
注意:检查终端顶部。代理在新选项卡(终端2)中运行,最近的命令在原始选项卡(终端1)中执行。代理仍然在第二个选项卡中运行,这使得curl命令可以使用localhost:8001
为了在不使用代理的情况下访问新部署,需要一个服务,下面即将进行讲解。
文档链接地址:https://kubernetes.io/zh/docs/tutorials/kubernetes-basics/explore/explore-intro/
在上面创建 Deployment 时, Kubernetes 添加了一个 Pod 来托管我们的应用实例。Pod 是 Kubernetes 抽象出来的,表示一组一个或多个应用程序容器(如 Docker),以及这些容器的一些共享资源。这些资源包括:
Pod 为特定于应用程序的“逻辑主机”建模,并且可以包含相对紧耦合的不同应用容器。例如,Pod 可能既包含带有 Node.js 应用的容器,也包含另一个不同的容器,用于提供 Node.js 网络服务器要发布的数据。Pod 中的容器共享 IP 地址和端口,始终位于同一位置并且共同调度,并在同一工作节点上的共享上下文中运行。
Pod是 Kubernetes 平台上的原子单元。 当我们在 Kubernetes 上创建 Deployment 时,该 Deployment 会在其中创建包含容器的 Pod (而不是直接创建容器)。每个 Pod 都与调度它的工作节点绑定,并保持在那里直到终止(根据重启策略)或删除。 如果工作节点发生故障,则会在群集中的其他可用工作节点上调度相同的 Pod。
一个 pod 总是运行在 工作节点。工作节点是 Kubernetes 中的参与计算的机器,可以是虚拟机或物理计算机,具体取决于集群。每个工作节点由主节点管理。工作节点可以有多个 pod ,Kubernetes 主节点会自动处理在群集中的工作节点上调度 pod 。 主节点的自动调度考量了每个工作节点上的可用资源。
每个 Kubernetes 工作节点至少运行:
上面我们使用了 Kubectl 命令行界面。下面将继续使用它来获取有关已部署的应用程序及其环境的信息。 最常见的操作可以使用以下 kubectl 命令完成:
可以使用这些命令查看应用程序的部署时间,当前状态,运行位置以及配置。
点击上图中“开始交互式教程”,进入如下图页面。
执行如下指令,查看所有已经存在的pod
查看pod包含的所有container容器、构建这些容器所使用的镜像,执行如下指令:
从上图可以看到,输出了pod相关的容器的详细信息:ip地址、端口号、这个pod生命周期相关的一系列事件
查看详情的describe也使用于:node, pods, deployments.
点击如下如“continue”,进入如下一个页面
我们需要创建一个proxy代理来接入隔离的、私有的kubernetes集群网络,使用kubectl proxy指令开启一个proxy代理,显示到另外一个终端窗口中。执行如下指令
echo -e "\n\n\n\e[92mStarting Proxy. After starting itwill not output a response. Please click the first Terminal Tab\n"; kubectl proxy
现在同样,我们将通过proxy代理获得pod名称和查询pod,获取pod名称并且将其存储到POD_NAME环境变量中。
运行如下curl请求去查看我们的应用的相关输出,这url就是pod api的路径。
curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
点击上图中的“continue”,进入如下图页面
应用程序通常发送到STDOUT的任何内容都将成为Pod中容器的日志。我们可以使用kubectl logs命令检索这些日志:
kubectl logs $POD_NAME
点击上图中的“continue”
一旦pod处于启动并运行状态,我们就可以在pod包含的容器中直接执行指令。
执行如下指令,列出指定pod的环境变量
kubectl exec $POD_NAME env
执行如下指令,在pod包含的容器中开启一个bash会话
kubectl exec -ti $POD_NAME bash
现在在运行我们的NodeJS应用程序的容器上就有了一个打开的控制台,应用程序的源代码位于server.js文件。执行如下指令,查看server.js的内容。
可以通过在bash会话中执行如下指令来验证应用是否在运行
执行如下指令,关闭到Pod包含容器的连接
文档链接:https://kubernetes.io/zh/docs/tutorials/kubernetes-basics/expose/expose-intro/
Kubernetes Pod 是转瞬即逝的。 Pod 实际上拥有 生命周期。 当一个工作 Node 挂掉后, 在 Node 上运行的 Pod 也会消亡。 ReplicaSet 会自动地通过创建新的 Pod 驱动集群回到目标状态,以保证应用程序正常运行。 换一个例子,考虑一个具有3个副本数的用作图像处理的后端程序。这些副本是可替换的; 前端系统不应该关心后端副本,即使 Pod 丢失或重新创建。也就是说,Kubernetes 集群中的每个 Pod (即使是在同一个 Node 上的 Pod )都有一个惟一的 IP 地址,因此需要一种方法自动协调 Pod 之间的变更,以便应用程序保持运行。
Kubernetes 中的服务(Service)是一种抽象概念,它定义了 Pod 的逻辑集和访问 Pod 的协议。Service 使从属 Pod 之间的松耦合成为可能。 和其他 Kubernetes 对象一样, Service 用 YAML 或者 JSON 来定义. Service 下的一组 Pod 通常由 LabelSelector来标记。
尽管每个 Pod 都有一个唯一的 IP 地址,但是如果没有 Service ,这些 IP 不会暴露在群集外部。Service 允许您的应用程序接收流量。Service 也可以用在 ServiceSpec 标记type
的方式暴露。
:
从集群外部访问 Service。是 ClusterIP 的超集。externalName
指定)公开 Service。不使用代理。这种类型需要kube-dns
的v1.7或更高版本。另外,需要注意的是有一些 Service 的用例没有在 spec 中定义selector
。 一个没有selector
创建的 Service 也不会创建相应的端点对象。这允许用户手动将服务映射到特定的端点。没有 selector 的另一种可能是您严格使用type: ExternalName
来标记。
Service 通过一组 Pod 路由通信。Service 是一种抽象,它允许 Pod 死亡并在 Kubernetes 中复制,而不会影响应用程序。在依赖的 Pod (如应用程序中的前端和后端组件)之间进行发现和路由是由Kubernetes Service 处理的。
Service 匹配一组 Pod 是使用 标签(Label)和选择器(Selector), 它们是允许对 Kubernetes 中的对象进行逻辑操作的一种分组原语。标签(Label)是附加在对象上的键/值对,可以以多种方式使用:
标签(Label)可以在创建时或之后附加到对象上。他们可以随时被修改。现在使用 Service 发布我们的应用程序并添加一些 Label 。
查看已经存在的所有的pod,执行如下指令:
kubectl get pods
查看当前集群中所有service,执行如下指令
kubectl get services
从上图可以看出,目前存在一个名称为“kubernetes”的服务,它是minikube启动集群时默认创建的。下面,我们来创建并暴露一个服务,使用expose 指令,NodePort作为参数(minikube不支持负载均衡选项)
kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
我们现在有了一个正在运行的service叫做kubernetes-bootcamp,它具有唯一的一个cluster-IP、内部端口和一个外部IP(节点的IP)。要找出外部打开了哪个端口(通过NodePort选项),我们将运行describe service命令
kubectl describe services/kubernetes-bootcamp
创建一个名为NODE_PORT的环境变量,该变量分配了NODE PORT的值。
export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{
{(index .spec.ports 0).nodePort}}')
现在我们可以使用curl、节点的IP和外部暴露的端口测试应用程序是否暴露在集群外部:
curl $(minikube ip):$NODE_PORT
我们得到服务器的响应。服务已暴露。
点击“continue”按钮,进入如下图页面:
创建Deployment 时会自动为pod创建了一个标签。使用describe deployment命令,可以看到标签的名称:
kubectl describe deployment
我们可以利用这个label去查询pod列表,使用命令kubectl get pods -l label值
kubectl get pods -l run=kubernetes-bootcamp
执行如下指令,查看已经存在的所有service
kubectl get services -l run=kubernetes-bootcamp
执行如下指令,获取pod的名称并将其存储到环境变量POD_NAME 中
export POD_NAME=$(kubectl get pods -o go-template --template'{
{range .items}}{
{.metadata.name}}{
{"\n"}}{
{end}}')
执行如下指令,给pod应用新的标签
kubectl label pod $POD_NAME app=v1
使用如下命令查看pod的标签
kubectl describe pods $POD_NAME
现在就可以使用这个新标签来查询pod
kubectl get pods -l app=v1
点击“continue”按钮,进入如下图页面
执行如下指令,删除一个service
kubectl delete service -l run=kubernetes-bootcamp
执行如下指令,查看所有的service,发现kubernetes-bootcamp服务已被删除
kubectl get services
为了验证路由不再暴露,可以使用curl指令
curl $(minikube ip):$NODE_PORT
这证明从集群外部无法再访问应用程序。你可以确认该应用程序仍在运行,在pod中执行curl
kubectl exec -ti $POD_NAME curl localhost:8080
我们在这里看到应用仍然处于启动状态。这是因为Deployment正在管理应用程序。要关闭应用程序,还需要删除Deployment。