
鸟瞰Kubernetes Minikube本身自带了一些好东西。你可以访问官方自带的面板:minikube dashboard 从这里,你可以查看你的集群详细信息和部署应用。 总结 现在你已经了解了在Windows上安装Docker和Kubernetes的所有选项。如果你遇到了文章没提到的错误,请通过@learnk8s或者slack告诉我们。接下来,你可以在你的环境里面部署更多应用了。请看文档。 本文转自DockOne-如何在Windows 10上运行Docker和Kubernetes?
今天是Google Developer Advocate Sandeep Dinesh的七部分视频和博客系列的第二部分,介绍如何充分利用您的Kubernetes环境。当您开始在Kubernetes之上构建越来越多的服务时,简单的任务开始变得更加复杂。 例如,团队无法创建具有相同名称的Kubernetes Service或Deployment。 如果你有成千上万的Pod,只是列出它们都需要一些时间,更不用说实际管理它们了!当然,这些还只是冰山一角。在本期Kubernetes最佳实践中,让我们来看看如何使用Kubernetes命名空间来更轻松地管理您的Kubernetes资源。 什么是命名空间(Namespace)? 您可以将命名空间视为Kubernetes集群中的虚拟集群。 您可以在单个Kubernetes集群中拥有多个命名空间,并且它们在逻辑上彼此隔离。 他们可以为您和您的团队提供组织,安全甚至性能方面的帮助!默认命名空间(Default Namespace) 在大多数Kubernetes发行版中,集群开箱即用,命名空间默认为default。事实上,Kubernetes上有三个命名空间:default、kube-system(用于Kubernetes组件)和kube-public( 用于公共资源)。 kube-public现在并没有真正使用过,而且通常单独隔离一个kube-system是个好主意,尤其是在Google Kubernetes Engine这样的托管系统中。 默认命名空间是你创建服务和应用程序的默认位置,如果你不指定namespace参数的话。这个命名空间绝对没有什么特别之处,只是Kubernetes工具是开箱即用的设置使用这个命名空间,而且你无法删除它。 它很适合入门和小型生产系统,我建议不要在大型生产系统中使用它。 这是因为团队很容易在没有意识到的情况下,意外地覆盖或破坏其他服务。 相反,我们应该创建多个命名空间并使用它们来将服务划分为可管理的块。创建命名空间 不要害怕创建命名空间。 它们不会增加性能损失,而且实际上,在许多情况下它们可以提高性能,因为这样的话Kubernetes API使用的是较小的对象集合。可以使用单个命令来创建命名空间。 如果你想创建一个名为test的命名空间,你可以运行如下命令:kubectl create namespace test 或者您可以像创建其他任何Kubernetes资源一样,创建一个YAML文件并应用它。test.yaml:kind: Namespace apiVersion: v1 metadata: name: test labels: name: test kubectl apply -f test.yaml 查看命名空间 您可以使用以下命令查看所有命名空间:kubectl get namespace 如上图,您可以看到三个内置命名空间,以及名为test的新命名空间。 在命名空间中创建资源 让我们看一个简单的YAML,它用来创建一个Pod:apiVersion: v1 kind: Pod metadata: name: mypod labels: name: mypod spec: containers: - name: mypod image: nginx 您可能会注意到在任何地方都没有提到名称空间。 如果在此文件上运行kubectl apply,它将在当前活动的命名空间中创建Pod。 除非您更改它,否则这将是“默认”命名空间。有两种方法可以明确告诉Kubernetes您要在哪个Namespace中创建资源。一种方法是在创建资源时设置namespace标识:kubectl apply -f pod.yaml --namespace=test 您还可以在YAML声明中指定命名空间:apiVersion: v1 kind: Pod metadata: name: mypod namespace: test labels: name: mypod spec: containers: - name: mypod image: nginx 如果在YAML声明中指定命名空间,则将始终在该命名空间中创建资源。如果您尝试使用namespace标志来设置另一个命名空间,则该命令将会失败。在命名空间中查看资源 如果你试图找到你的Pod,你可能会注意到你不能!$ kubectl get pods No resources found. 这是因为所有命令都是针对当前active的命名空间运行的。 要查找Pod,您需要指定namespace。$ kubectl get pods --namespace=test NAME READY STATUS RESTARTS AGE mypod 1/1 Running 0 10s 这可能会很快让人觉得很烦,特别是如果您是一个开发团队的开发人员,该团队使用自己的命名空间来处理所有事情,并且不希望对每个命令都指定namespace。 让我们看看我们如何解决这个问题。管理active命名空间 初始状态下,您的活动命名空间是default。 除非在YAML中指定命名空间,否则所有Kubernetes命令都将使用当前active命名空间。不幸的是,尝试使用kubectl管理您的active命名空间可能会很痛苦。 幸运的是,有一个非常好的工具叫做kubens(由优秀的Ahmet Alp Balkan创建)可以让它变得轻而易举!运行kubens命令时,您应该看到所有命名空间,并突出显示active命名空间: 要将active命名空间切换到test命名空间,请运行: kubens test 现在您可以看到test命名空间处于active状态: 现在,如果你运行kubectl命令,命名空间将是test而不是default! 这意味着您不需要指定命名空间来查看测试命名空间中的Pod。$ kubectl get pods NAME READY STATUS RESTARTS AGE mypod 1/1 Running 0 10m 跨命名空间通信 命名空间彼此“隐藏”,但默认情况下它们不是完全隔离的。一个命名空间中的服务可以与另一个命名空间中的服务进行通信。 这通常非常有用,例如让您的团队的服务(在您的命名空间中)与另一个团队的服务(在另一个命名空间中)进行通信。当您的应用想要访问Kubernetes Service时,您可以使用内置的DNS服务发现,只需将您的应用指向该Service的名称即可。 但是,您可以在多个命名空间中创建具有相同名称的Service!值得庆幸的是,通过使用扩展形式的DNS地址很容易解决这个问题。Kubernetes中的服务使用通用DNS模式公开其endpoint。 它看起来像这样:<Service Name>.<Namespace Name>.svc.cluster.local 通常,您只需要服务名称,DNS将自动解析为完整地址。 但是,如果需要访问另一个命名空间中的服务,则需使用服务名称加上命名空间名称。例如,如果要连接到test命名空间中的database服务,可以使用以下地址:database.test 如果要连接到production命名空间中的database服务,可以使用以下地址:database.production 警告:如果您创建一个映射到“com”或“org”等TLD的命名空间,然后创建一个与网站名称相同的服务,例如“google”或“reddit”,Kubernetes将拦截“google.com“或”reddit.com“的请求并将其发送到您的服务。 这通常对于测试和代理非常有用,但也可以轻松破坏集群中的内容!注意:如果确实要隔离命名空间,则应使用网络策略(Network Policies)来完成此操作。 更多信息请继续关注未来剧集!命令空间粒度 一个常见问题是要创建多少个命名空间以及用于何种目的。 什么是可管理的块? 创建太多的命名空间,它们会让你变得没有效率,但是创建太少,你会错过它们的好处。我认为答案在于您的项目或公司处于什么阶段 ——从小团队到成熟企业,每个阶段都有自己的组织架构。 根据您的具体情况,您可以采用对应的命名空间策略。小团队 在这种情况下,您是一个小团队的一员,该团队正在开发5-10个微服务,可以轻松地进行团队沟通。 在这种情况下,将所有生产服务放到“默认”命名空间是个不错的选择。 根据你的个人喜好,你可能希望有一个production和development的命名空间,但你很有可能是在本地机器上使用类似Minikube搭建的开发环境。快速成长的团队 在这种情况下,您有一个快速发展的团队,正在开发10多个微服务。 您开始将团队分成多个子团队,每个团队都拥有自己的微服务。 虽然每个人都可能知道整个系统是如何工作的,但是与其他人协调每一个变化变得越来越困难。 尝试在本地计算机上启动整个堆栈每天都变得越来越复杂。此时有必要使用多个集群或命名空间进行生产和开发。 每个团队可以选择拥有自己的命名空间,以便于管理。大公司 在一家大公司,并不是每个人都了解其他人。 某个团队正致力于其他团队可能不了解的功能。 团队可能正在使用服契约(service contract)与其他微服务通信(例如,gRPC),也有可能使用服务网格(Service Mesh)进行通信(例如,istio)。 试图在本地运行整个堆栈是不可能的。 强烈建议使用Kubernetes-aware Continuous Delivery系统(例如,Spinnaker)。此时,每个团队肯定需要自己的命名空间。 每个团队甚至可以选择多个名称空间来运行其开发和生产环境。 设置RBAC和ResourceQuotas也是一个好主意。 多个集群开始显得很有意义,但可能不一定是必要的。注意:我将在后面的文章中深入研究gRPC、Istio、Spinnaker、RBAC和Resources!企业 在这种规模下,有些群体甚至不知道其他群体的存在。 某个组也可能是外部公司,服务之间通过标准文档定义的API来通信。 每个小组都有多个拥有一定数量微服务的团队。 这时使用我上面提到的所有工具是必要的。 人们不应该手工部署服务,同时应该被锁定在他们不拥有的命名空间之外。此时,拥有多个集群以减少配置不当的应用程序导致的爆炸半径,以及简化计费和资源管理可能是有意义的。 结论 命名空间可以帮助您组织Kubernetes资源,同时可以提高团队的开发速度。 请继续关注未来的Kubernetes最佳实践剧集,我将向您展示如何锁定命名空间中的资源并为您的群集引入更多安全性和隔离性! 本文转自DockOne-Kubernetes最佳实践S01E02:如何使用命名空间管理Kubernetes资源?
今天是Google Developer Advocate Sandeep Dinesh关于如何充分利用Kubernetes环境的七部分视频和博客系列的第三部分。分布式系统很难管理。 一个重要原因是有许多动态部件都为系统运行起作用。 如果一个小部件损坏,系统必须检测它,绕过它并修复它。 这一切都需要自动完成!健康检查(Health Check)是让系统知道您的应用实例是否正常工作的简单方法。 如果您的应用实例不再工作,则其他服务不应访问该应用或向其发送请求。 相反,应该将请求发送到已准备好的应用程序实例,或稍后重试。 系统还应该能够使您的应用程序恢复健康状态。 默认情况下,当Pod中的所有容器启动时,Kubernetes开始向Pod发送流量,并在崩溃时重新启动容器。 虽然这在开始时可以“足够好”,但您还可以通过创建自定义运行状况检查来使部署更加健壮。 幸运的是,Kubernetes使这个相对简单,所以没有理由不去这么干! 在本期Kubernetes最佳实践中,让我们了解readiness和liveness探针的细节,何时使用哪种探针,以及如何在Kubernetes集群中进行设置。健康检查的类型 Kubernetes为您提供两种类型的健康检查,了解两者之间的差异及其用途非常重要。Readiness Readiness探针旨在让Kubernetes知道您的应用何时准备好其流量服务。 Kubernetes确保Readiness探针检测通过,然后允许服务将流量发送到Pod。 如果Readiness探针开始失败,Kubernetes将停止向该容器发送流量,直到它通过。Liveness Liveness探针让Kubernetes知道你的应用程序是活着还是死了。 如果你的应用程序还活着,那么Kubernetes就不管它了。 如果你的应用程序已经死了,Kubernetes将删除Pod并启动一个新的替换它。健康检查是如何提供帮助的? 让我们看看两个场景,Readiness探针和Liveness探针可以帮助您构建鲁棒性更强的应用程序。Readiness 让我们假设您的应用需要一分钟的时间来预热并开始。 即使该过程已启动,您的服务在启动并运行之前也无法运行。 如果要将此部署扩展为具有多个副本,也会出现问题。 新副本在完全就绪之前不应接收流量,但默认情况下,Kubernetes会在容器内的进程启动后立即开始发送流量。 通过使用Readiness探针,Kubernetes等待应用程序完全启动,然后才允许服务将流量发送到新副本。Liveness 让我们假设另一种情况,你的应用程序有一个令人讨厌的死锁情况,导致它无限期挂起并停止提供请求服务。 因为该服务还在运行,默认情况下Kubernetes认为一切正常并继续向已经broken的Pod发送请求。 通过使用Liveness探针,Kubernetes会检测到应用程序不再提供请求并重新启动有问题的Pod。探针类型 下一步是定义测试Readiness和Liveness的探针。 有三种类型的探测:HTTP、Command和TCP。 您可以使用它们中的任何一个进行Liveness和Readiness检查。HTTP HTTP探针可能是最常见的自定义Liveness探针类型。 即使您的应用程序不是HTTP服务,您也可以在应用程序内创建轻量级HTTP服务以响应Liveness探针。 Kubernetes去ping一个路径,如果它得到的是200或300范围内的HTTP响应,它会将应用程序标记为健康。 否则它被标记为不健康。您可以在此处阅读有关HTTP探针的更多信息。Command 对于Command探针,Kubernetes则只是在容器内运行命令。 如果命令以退出代码0返回,则容器标记为健康。 否则,它被标记为不健康。 当您不能或不想运行HTTP服务时,此类型的探针则很有用,但是必须是运行可以检查您的应用程序是否健康的命令。您可以在此处阅读有关Command探针的更多信息。TCP 最后一种类型的探针是TCP探针,Kubernetes尝试在指定端口上建立TCP连接。 如果它可以建立连接,则容器被认为是健康的;否则被认为是不健康的。如果您有HTTP探针或Command探针不能正常工作的情况,TCP探测器会派上用场。 例如,gRPC或FTP服务是此类探测的主要候选者。您可以在此处阅读有关TCP探针的更多信息。配置探针的初始化延迟时间 可以通过多种方式配置探针。 您可以指定它们应该运行的频率,成功和失败阈值是什么,以及等待响应的时间。 有关配置探针的文档非常清楚地介绍了其不同的选项及功能。但是,使用Liveness探针时需要配置一个非常重要的设置,就是initialDelaySeconds设置。如上所述,Liveness探针失败会导致Pod重新启动。 在应用程序准备好之前,您需要确保探针不会启动。 否则,应用程序将不断重启,永远不会准备好!我建议使用p99延迟启动时间作为initialDelaySeconds,或者只是取平均启动时间并添加一个缓冲区。 随着您应用的启动时间变得越来越快,请确保更新这个数值。结论 大多数人会告诉你健康检查是分布式系统的基本要求,Kubernetes也不例外。 使用健康检查为您的Kubernetes服务奠定了坚实的基础,更好的可靠性和更长的正常运行时间。 值得庆幸的是,Kubernetes让您轻松做到这些! 本文转自DockOne-Kubernetes最佳实践S01E03:Kubernetes集群健康检查最佳实践
这是Google Developer Advocate Sandeep Dinesh关于如何充分利用Kubernetes环境的七部分视频和博客系列的第六部分。如果您像大多数Kubernetes用户一样,您可能会使用群集外的服务。 例如,您可能使用Twillio API发送短信,或者使用Google Cloud Vision API进行图像分析。如果您的不同环境中的应用程序连接到同一外部端点,并且没有计划将外部服务引入Kubernetes集群,则可以直接在代码中使用外部服务端点。 但是,在许多情况下情况并非如此。 一个很好的例子是数据库。 虽然某些云原生数据库(如Cloud Firestore或Cloud Spanner)使用单个端点进行所有访问,但大多数数据库都有针对不同实例的单独端点。此时,您可能认为找到端点的一个好方法是使用ConfigMaps。 只需将端点地址存储在ConfigMap中,并在代码中将其用作环境变量。 虽然这种解决方案有效,但也存在一些缺点。 您需要修改部署以包含ConfigMap并编写其他代码以从环境变量中读取。 但最重要的是,如果端点地址发生更改,则可能需要重新启动所有正在运行的容器以获取更新的端点地址。在本期“Kubernetes最佳实践”中,让我们学习如何利用Kubernetes的内置服务发现机制来运行集群外部的服务,就像集群内的服务一样! 这使您可以在dev和prod环境中进行校验,最终只需要在集群中迁移服务,而根本不必更改代码。场景1:具有IP地址的群集外的数据库 一种非常常见的情况是您托管自己的数据库,但在群集外部执行此操作,例如在Google Compute Engine实例上。 如果您在Kubernetes内部和外部运行某些服务,或者需要比Kubernetes允许的更多自定义或控制,这是非常常见的。您希望在某些时候,可以迁移集群内的所有服务,但在此之前,您将生活在混合世界中。 值得庆幸的是,您可以使用静态Kubernetes服务来缓解一些痛苦。在此示例中,我使用Cloud Launcher创建了一个MongoDB服务器。 由于它是在与Kubernetes集群相同的网络(或VPC)中创建的,因此可以使用高性能内部IP地址进行访问。 在Google Cloud中,这是默认设置,因此您无需任何特殊配置。现在我们有了IP地址,第一步是创建服务: kind: Service apiVersion: v1 metadata: name: mongo Spec: type: ClusterIP ports: - port: 27017 targetPort: 27017 您可能会注意到此服务没有Pod选择器。 这会创建一个服务,但它不知道在哪里发送流量。 这允许您手动创建将从此服务接收流量的Endpoints对象。kind: Endpoints apiVersion: v1 metadata: name: mongo subsets: - addresses: - ip: 10.240.0.4 ports: - port: 27017 您可以看到端点手动定义数据库的IP地址,并使用与服务相同的名称。 Kubernetes使用端点中定义的所有IP地址,就像它们是常规的Kubernetes Pod一样。 现在,您可以使用简单的连接字符串访问数据库:mongodb://mongo 根本不需要在代码中使用IP地址! 如果将来IP地址发生变化,您可以使用新IP地址更新端点,并且您的应用程序无需进行任何更改。 场景2:具有URI的远程托管数据库 如果您使用来自第三方的托管数据库服务,则可能会为您提供可用于连接的统一资源标识符(URI)。 如果他们为您提供IP地址,则可以使用方案1中的方法。在这个例子中,我有两个在mLab上托管的MongoDB数据库。 其中一个是我的开发数据库,另一个是生产。这些数据库的连接字符串如下: mongodb://<dbuser>:<dbpassword>@ds149763.mlab.com:49763/dev mongodb://<dbuser>:<dbpassword>@ds145868.mlab.com:45868/prod mLab为您提供动态URI和动态端口,您可以看到它们都是不同的。 让我们使用Kubernetes为这些差异创建一个抽象层。 在这个例子中,让我们连接到dev数据库。您可以创建一个叫“ExternalName”的Kubernetes服务,它为您提供静态Kubernetes服务,将流量重定向到外部服务。 此服务在内核级别执行简单的CNAME重定向,因此对性能的影响非常小。该服务的YAML如下所示:kind: Service apiVersion: v1 metadata: name: mongo spec: type: ExternalName externalName: ds149763.mlab.com 现在,您可以使用更简化的连接字符串:mongodb://<dbuser>:<dbpassword>@mongo:<port>/dev 由于“ExternalName”使用CNAME重定向,因此无法进行端口重新映射。 对于具有静态端口的服务,这可能没问题,但不幸的是,在示例中它的端口是动态的。 mLab的免费套餐为您提供动态端口号,您无法更改它。 这意味着您需要为dev和prod使用不同的连接字符串。但是,如果你可以获得IP地址,那么你可以进行端口重映射,我将在下一篇中解释。场景3:具有URI和端口重新映射的远程托管数据库 虽然CNAME重定向适用于每个环境具有相同端口的服务,但在每个环境的不同端点使用不同端口的情况下,它略显不足。 谢天谢地,我们可以使用一些基本工具解决这个问题。第一步是从URI获取IP地址。如果对URI运行nslookup,hostname或ping命令,则可以获取数据库的IP地址。您现在可以创建重新映射mLab端口的服务以及此IP地址的端点。 kind: Service apiVersion: v1 metadata: name: mongo spec: ports: - port: 27017 targetPort: 49763 --- kind: Endpoints apiVersion: v1 metadata: name: mongo subsets: - addresses: - ip: 35.188.8.12 ports: - port: 49763 注意:URI可能使用DNS对多个IP地址进行负载均衡,因此如果IP地址发生变化,此方法可能存在风险! 如果从上面的命令中获得多个IP地址,则可以将所有这些地址包含在端点YAML中,并且Kubernetes将对所有IP地址的流量进行负载均衡。这样,您无需指定端口即可连接到远程数据库。 Kubernetes服务透明地重新映射端口!mongodb://<dbuser>:<dbpassword>@mongo/dev 结论 将外部服务映射成内部服务使您可以灵活地将这些服务引入集群,同时最大限度地减少重构工作。 即使你今天不计划这么做,那你也永远不知道明天会发生什么! 此外,它还可以更轻松地管理和了解您的组织正在使用哪些外部服务。如果外部服务具有有效的域名并且您不需要端口重新映射,则使用“ExternalName”服务类型是将外部服务映射到内部服务的简单快捷的方法。 如果您没有域名或需要进行端口重新映射,只需将IP地址添加到端点并使用它。 本文转自DockOne-Kubernetes最佳实践S01E06:Kubernetes的内置服务发现机制运行集群外部服务
每个人都知道,保持应用程序最新以及优化安全性和性能是一种很好的做法。 Kubernetes和Docker可以更轻松地执行这些更新,因为您可以使用更新构建新容器并相对轻松地部署它。就像您的应用程序一样,Kubernetes不断获得新功能和安全更新,因此底层节点和Kubernetes基础架构也需要保持最新。在本期Kubernetes最佳实践中,让我们来看看Google Kubernetes Engine如何让您的Kubernetes集群轻松升级!集群的两个部分:Master和Node 在升级群集时,需要更新两个部分:Mater和Node。 需要首先更新Master,Node随后。 让我们看看如何使用Kubernetes Engine升级它们。零停机更新Master Kubernetes Engine会在发布点发布时会自动升级Master,但通常不会自动升级到新版本(例如,1.7到1.8)。 准备好升级到新版本后,只需单击Kubernetes Engine控制台中的升级主按钮即可。但是,您可能已经注意到该对话框显示以下内容: “更改主版本可能会导致几分钟的控制平面停机。 在此期间,您将无法编辑此群集。”当主服务器关闭进行升级时,deployments,services将继续按预期工作。 但是,任何需要Kubernetes API的东西都会停止工作。 这意味着kubectl将停止工作,那些使用Kubernetes API获取有关群集信息的应用程序将停止工作,您基本上无法在集群升级时对群集进行任何更改。那么如何更新Master而不会导致停机呢?具有Kubernetes Engine区域集群的高可用Masters 虽然标准的zonal Kubernetes Engine集群只有一个Master支持它们,但您可以创建regional集群,提供多区域,高可用性的Master(注意:Kubernetes Engine区域集群最近普遍可用)。创建群集时,请务必选择regional选项: 就是这样! Kubernetes引擎自动在三个zone中创建Node和Master,Master位于负载平衡的IP地址后面,因此Kubernetes API将在升级期间继续工作。 零停机更新Node 升级节点时,您可以使用几种不同的策略。 我想关注两个: 滚动更新 使用节点池迁移 滚动更新 更新Kubernetes Node的最简单方法是使用滚动更新。 这是Kubernetes Engine用于更新Node的默认升级机制。滚动更新以下列方式工作。 一个接一个,一个释放,一个锁存,直到该Node上不再运行Pod。 然后删除该Node,并使用更新的Kubernetes版本创建新Node。 该Node启动并运行后,将更新下一个Node。 这一直持续到所有Node都更新为止。您可以通过在节点池(Node Pool)上启用自动节点升级,让Kubernetes Engine完全为您管理此过程。 如果您不选择此选项,Kubernetes Engine仪表板会在升级可用时提醒您: 只需单击该链接,然后按照提示开始滚动更新。 警告:确保您的Pod由ReplicaSet,Deployment,StatefulSet或类似的东西管理。 独立Pod不会被重新调度!虽然在Kubernetes Engine上执行滚动更新很简单,但它有一些缺点。一个缺点是您在群集中获得的节点容量少一个。 通过扩展节点池以添加额外容量,然后在升级完成后将其缩小,可以轻松解决此问题。滚动更新的完全自动化特性使其易于操作,但您对该过程的控制较少。 如果出现问题,还需要时间回滚到旧版本,因为您必须停止滚动更新然后撤消它。使用节点池(Node Pool)迁移 您可以创建新节点池,等待所有节点运行,然后一次在一个节点上迁移工作负载,而不是像滚动更新那样升级“活跃的”节点池。我们假设我们的Kubernetes集群现在有三个VM。 您可以使用以下命令查看节点:kubectl get nodes NAME STATUS AGE gke-cluster-1-default-pool-7d6b79ce-0s6z Ready 3h gke-cluster-1-default-pool-7d6b79ce-9kkm Ready 3h gke-cluster-1-default-pool-7d6b79ce-j6ch Ready 3h 创建新的节点池 要创建名为pool-two的新节点池,请运行以下命令:gcloud container node-pools create pool-two 注意:请记住此自定义命令,以便新节点池与旧池相同。 如果需要,还可以使用Kubernetes Engine GUI创建新节点池。现在,如果您检查节点,您会注意到有三个节点具有新池名称:$ kubectl get nodes NAME STATUS AGE gke-cluster-1-pool-two-9ca78aa9–5gmk Ready 1m gke-cluster-1-pool-two-9ca78aa9–5w6w Ready 1m gke-cluster-1-pool-two-9ca78aa9-v88c Ready 1m gke-cluster-1-default-pool-7d6b79ce-0s6z Ready 3h gke-cluster-1-default-pool-7d6b79ce-9kkm Ready 3h gke-cluster-1-default-pool-7d6b79ce-j6ch Ready 3h 但是,Pod仍然在旧节点上! 让我们来迁移Pod到新节点上。释放旧节点池 现在我们需要将工作负载迁移到新节点池。 让我们以滚动的方式一次迁移一个节点。首先,cordon(隔离)每个旧节点。 这将阻止新的Pod安排到它们上面。kubectl cordon <node_name> 一旦所有旧节点都被隔离,就只能将Pod调度到新节点上。 这意味着您可以开始从旧节点中删除Pod,Kubernetes会自动在新节点上调度它们。警告:确保您的Pod由ReplicaSet,Deployment,StatefulSet或类似的东西管理。 独立Pod不会被重新调度!运行以下命令以释放每个节点。 这将删除该节点上的所有Pod。kubectl drain <node_name> --force 释放节点后,确保新的Pod已启动并运行,然后再转到下一个节点。如果您在迁移过程中遇到任何问题,请取消旧池的保护,然后隔离并释放新池。 Pod会被重新调度回旧池。删除旧节点池 一旦所有Pod安全地重新调度,就可以删除旧池了。将default-pool替换为要删除的池。gcloud container node-pools delete default-pool 您刚刚成功更新了所有节点!结论 通过使用Kubernetes Engine,您只需点击几下即可使Kubernetes集群保持最新状态。如果您没有使用像Kubernetes Engine这样的托管服务,您仍然可以将滚动更新或节点池方法用在您自己的集群升级上。 不同之处在于您需要手动将新节点添加到集群中,并自行执行主升级,这可能很棘手。我强烈建议使用Kubernetes Engine regional集群来实现高可用Master和自动节点升级,以获得无烦恼的升级体验。 如果您需要对节点更新进行额外控制,则使用节点池可以为您提供该控制,而不会放弃Kubernetes Engine为您提供的托管Kubernetes平台的优势。到这里,我们要结束关于Kubernetes最佳实践的系列文章的第一季了。 如果您对希望我解决的其他主题有所了解,可以在Twitter上找到我。 本文转自DockOne-Kubernetes最佳实践S01E07:零停机更新Kubernetes集群