Kubernetes tutorial - K8S 官方入门教程 中文翻译

2023-05-16

官方教程,共 6 个小节。每一小节的第一部分是知识讲解,第二部分是在线测试环境的入口。
kubectl 的命令手册
原文地址

1 创建集群

1.1 使用 Minikube 创建集群

Kubernetes 集群

Kubernetes 协调一个高可用的计算机集群,这个集群连接到一起作为一个单元工作。通过 Kubernetes 中的抽象,可以将容器化应用程序部署到集群,而不必将它们绑定到单个机器上。为了使用这种新的部署模式,应用程序需要以一种将它们与单个主机分离的方式进行打包:容器化。在过去的部署模型中,应用程序作为深度集成到主机中的包直接安装到特定的机器上,相比之下,容器化应用程序更加灵活可用。Kubernetes 以更高效的方式自动化跨集群的应用程序容器的分发和调度。Kubernetes 是一个开放源代码的平台,可以在生产环境中使用。

Kubernetes 集群由两种类型的资源组成:

  • 用于协调集群的 Master
  • 用于作为 worker 运行应用程序的 Node

Kubernetes 是一个生产级的开源平台,负责协调计算机集群内部和跨集群应用程序容器的布局(调度)和执行。

集群图

这里写图片描述

Master 负责管理集群。Master 协调集群中的所有活动,例如调度应用程序,维护应用程序的期望状态,扩展应用程序以及滚动升级。

Node 节点是 Kubernetes 集群中的 worker 工作节点,可以是虚拟机或物理机。每个节点都安装了 Kubelet,用于管理节点并与 Kubernetes 的 Master 进行通信。每个节点还应具有处理容器操作的工具,例如 Docker 或 rkt。处理生产环境中的流量的 Kubernetes 集群至少需要有三个节点。

Master 用于管理集群,Node 节点用于托管要运行的应用程序。

在 Kubernetes 上部署应用程序时,需要告知 Master 启动应用程序容器。Master 会规划容器运行在集群的某个节点上。每个节点通过 Master 暴露的 Kubernetes API 与 Master 通信。终端用户也可以通过 Kubernetes API 直接与集群交互。

Kubernetes 集群可以部署到物理机或虚拟机上。可以使用 Minikube 来学习 Kubernetes 的部署过程。Minikube 是一个轻量级的 Kubernetes 实现,可以在你的机器上创建虚拟机并部署一个只有单个节点的简单集群。Minikube 可以在 Linux、macOS 或 Windows 上安装。Minikube CLI 命令行界面提供了用于你的集群的基本启动操作,包括 start、stop、status 以及 delete。但是对于这个教程,你会使用一个预先安装了 Minikube 的在线终端。

1.2 交互式教程

Step 1 启动并运行集群

在线终端已经安装好了 Minikube。运行下面的命令确认一下:

minikube version

确认无误后,启动集群:

minikube start

现在,在线终端上有运行中的 Kubernetes 集群了。Minikube 会启动一个虚拟机,Kubernetes 集群运行在虚拟机上。

Step 2 集群的版本

通过 kubectl 命令可以根 Kubernetes 交互。运行 kubectl version 命令查看 kubectl 是否安装成功:

kubectl version

这里会同时看到 client 和 server 两个版本号。其中,client 对应 kubectl 的版本,server 对应 Master 上安装的 Kubernetes 的版本。这里也会显示构建的详情。

Step 3 集群详情

通过 kubectl cluster-info 命令查看集群的详情:

kubectl cluster-info

我们有一个运行中的 Master 和一个 Dashboard。Kubernetes Dashboard 允许你通过 UI 用户界面查看应用程序。在本教程中,我们将专注于通过命令行部署和探索应用程序。运行 kubectl get nodes 命令查看集群中的 Node 节点:

kubectl get nodes

这会显示所有可用于应用程序的节点。现在我们只有一个节点,且其 status 状态是 ready,表示可以用于部署应用程序。

2 部署应用程序

2.1 使用 kubectl 创建 Deployment

Kubernetes Deployments

一旦运行了 Kubernetes 集群,就可以在其上部署容器化的应用程序。为此,需要创建一个 Deployment 用于部署应用程序。Deployment 指示 Kubernetes 如何创建和更新应用程序的实例。创建 Deployment 后,Kubernetes Master 会将应用程序实例分配到集群中的独立节点上。

创建应用程序实例后,Deployment Controller 会一直监控这些实例。如果运行实例的节点出现故障或被删除,则 Deployment Controller 将替换这些节点。这提供了一种自我修复机制来应对机器故障或维护。

在编排前的世界中,安装脚本通常用于启动应用程序,但无法从机器故障中恢复。通过创建应用程序实例并保持它们跨节点运行,Kubernetes Deployment 为应用程序管理提供了一种完全不同的方法。

Deployment 负责创建和更新应用程序的实例

在 Kubernetes 上部署第一个应用程序

这里写图片描述
可以通过 Kubectl 这个命令行接口来创建并管理 Deployment。Kubectl 使用 Kubernetes API 来跟集群交互。在这一部分你会学习最常用的 Kubectl 命令,创建一个用于在 Kubernetes 集群上运行应用程序的 Deployment。

Deployment 创建完成后,需要为你的应用程序指定容器镜像及需要运行的副本(replicas)数量。可以在后面通过更新 Deployment 来改变这些设置,本教程的第 5 节和第 6 节讲述了如何伸缩及更新 Deployment。

要部署到 Kubernetes 中,应用程序必须打包为 Kubernetes 支持的容器格式。

对于第一个 Deployment,我们会使用一个打包为 Docker 容器的 Node.js 应用。源代码和 Dockerfile 可以在 Kubernetes Bootcamp 的 GitHub 仓库 中下载。

2.2 交互式教程

Step 1 kubectl 基础

类似 Minikube,Kubectl 也安装在在线终端中。输入 kubectl 可以查看命令的具体用法。Kubectl 命令的常用格式是:kubectl 动作 资源。这会在指定的资源(例如 node、container)上执行指定的动作(例如 create、get、describe)。可以在每个可能的参数后面使用 --help 来查看额外信息(kubectl get nodes --help)。

$ kubectl
kubectl controls the Kubernetes cluster manager.

Find more information at: https://kubernetes.io/docs/reference/kubectl/overview/

Basic Commands (Beginner):
  create         Create a resource from a file or from stdin.
  expose         Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service
  run            Run a particular image on the cluster
  set            Set specific features on objects
  run-container  Run a particular image on the cluster. This command is deprecated, use "run" instead

Basic Commands (Intermediate):
  get            Display one or many resources
  explain        Documentation of resources
  edit           Edit a resource on the server
  delete         Delete resources by filenames, stdin, resources and names, or by resources and label selector

Deploy Commands:
  rollout        Manage the rollout of a resource
  rolling-update Perform a rolling update of the given ReplicationController
  scale          Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job
  autoscale      Auto-scale a Deployment, ReplicaSet, or ReplicationController

Cluster Management Commands:
  certificate    Modify certificate resources.
  cluster-info   Display cluster info
  top            Display Resource (CPU/Memory/Storage) usage.
  cordon         Mark node as unschedulable
  uncordon       Mark node as schedulable
  drain          Drain node in preparation for maintenance
  taint          Update the taints on one or more nodes

Troubleshooting and Debugging Commands:
  describe       Show details of a specific resource or group of resources
  logs           Print the logs for a container in a pod
  attach         Attach to a running container
  exec           Execute a command in a container
  port-forward   Forward one or more local ports to a pod
  proxy          Run a proxy to the Kubernetes API server
  cp             Copy files and directories to and from containers.
  auth           Inspect authorization

Advanced Commands:
  apply          Apply a configuration to a resource by filename or stdin
  patch          Update field(s) of a resource using strategic merge patch
  replace        Replace a resource by filename or stdin
  convert        Convert config files between different API versions

Settings Commands:
  label          Update the labels on a resource
  annotate       Update the annotations on a resource
  completion     Output shell completion code for the specified shell (bash or zsh)

Other Commands:
  api-versions   Print the supported API versions on the server, in the form of "group/version"
  config         Modify kubeconfig files
  help           Help about any command
  plugin         Runs a command-line plugin
  version        Print the client and server version information

Usage:
  kubectl [flags] [options]

Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all
commands).

运行 kubectl version 命令来确认 kubectl 是否已经配置为与集群交互:

kubectl version

如果同时看到了 client 和 server 的版本信息,则配置无误。

通过下面命令查看集群中的节点:

kubectl get nodes

现在我们的例子中只能看到一个节点。Kubernetes 会根据 Node 的可用资源的不同来选择一个最合适的 Node 部署应用程序。

Step 2 部署应用

现在,通过 kubectl run 命令在 Kubernetes 上运行我们的第一个应用。run 命令会创建一个新的 Deployment。我们需要提供 Deployment 的名字以及应用程序的镜像位置(如果不是 Docker Hub,则需要提供完整的仓库 URL)。可以通过 --port 参数使应用运行在特定端口上。国内无法访问 gcr.io,需要替换:

kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080

注意,这里因为 墙 的问题,需要替换镜像路径为 jocatalin/kubernetes-bootcamp,完整命令如下:

kubectl run kubernetes-bootcamp --image=jocatalin/kubernetes-bootcamp:v1 --port=8080

如果需要删除所有通过 kubectl run 命令创建的 Deployment,可以运行下面命令:

kubectl delete deployments --all

现在,通过创建 Deployment 已经成功部署了第一个应用。这为你做了几件事情:

  • 搜索可以运行应用程序实例的合适节点(我们只有 1 个可用节点)
  • 调度应用程序在该节点上运行
  • 配置集群以在需要时将实例重新规划到新节点上

通过下面命令列出所有的 Deployment:

kubectl get deployments

这里会看到一个 Deployment,其中运行着应用程序的一个实例。实例运行在节点的 Docker 容器内。

Step 3 查看应用

Kubernetes 中运行的 Pod 运行在私有的隔离网络中。默认情况下,Pod 仅对同一个 Kubernetes 集群中的 service 和其他 Pod 可见。当我们使用 kubectl 时,会通过 API 终端交互,实现与应用程序的通信。

在第 4 小节,会讲解如何使用将应用暴露到 kubernetes 集群之外的选项。

kubectl 命令可以创建代理,将通信转发到集群范围的专用网络。代理可以通过 control-C 终止,并且在运行时不会显示任何输出。

打开第二个终端窗口来运行代理(或者以后台程序 & 的方式在同一个终端中运行):

kubectl proxy

现在,在我们的主机(在线终端)和 Kubernetes 集群之间通过代理建立了连接。通过代理可以从终端直接访问 Kubernetes API。

可以在使用 proxy 开启了代理的终端上,通过 http://localhost:8001 查看所有 API。例如,可以使用 curl 命令直接通过 API 查询版本:

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

然后,向 Pod 中运行的应用发送 HTTP 请求:

curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/

URL 就是 Pod 中对应的 API 的路由。

注意:代理需要保持开启状态。官方示例需要新开页签并执行 kubectl proxy 指令。当然,也可以在原页签中后台执行这个命令 kubectl proxy &

3 探索你的应用

3.1 查看 Pod 和 Node

Pod

在上一节中创建了 Deployment 之后,Kubernetes 会创建 Pod 用于托管应用实例。Pod 是一个 Kubernetes 抽象,表示一个由一个或多个应用容器(Docker 或 rkt)及用于这些容器的共享资源组成的分组。这些资源包括:

  • 共享存储,作为 Volume 卷
  • 网络,作为唯一的集群 IP 地址
  • 信息,描述如何运行每个容器,例如容器映像版本或要使用的特定端口

Pod 模拟了特定于应用程序的“逻辑主机”,并且可以包含相对紧密耦合的不同的应用程序容器。例如,Pod 可能包含一个带有 Node.js 应用程序的容器,以及另一个用于向 Node.js Web 服务器提供数据的容器。Pod 中的容器共享一个 IP 地址和端口空间,它们总是地址相同、共同调度(co-located and co-scheduled),并在同一个节点上的共享上下文中运行。

Pod 是 Kubernetes 平台上的原子单元。当在 Kubernetes 上创建一个 Deployment 时,该 Deployment 将创建带有容器的 Pod(而不是直接创建容器)。每个 Pod 在调度到某个节点后,会与该节点绑定,并保持在该位置直到终止(根据重启策略)或删除。如果发生节点故障,则会在集群中的其他可用节点上调度相同的 Pod。

Pod 概览图

这里写图片描述

Node

Pod 总是在 Node 上运行。Node 是 Kubernetes 中的工作机器,可能是虚拟机或物理机,具体取决于集群。每个 Node 由 Master 管理。一个 Node 上可以有多个 Pod,并且 Kubernetes Master 会自动在集群中的 Node 上调度 Pod。Master 的自动调度考虑了每个节点上的可用资源。

每个 Kubernetes Node 节点至少运行:

  • Kubelet,负责 Kubernetes Master 与 Node 之间的通信,并管理机器上运行的 Pod 和容器。
  • 一个容器运行时(如 Docker,rkt),负责从 registry 中获取容器镜像,解包容器并运行应用程序。

如果容器紧密耦合并需要共享资源(如磁盘),则只能将它们一起安排在一个 Pod 中。

Node 概览图

这里写图片描述

使用 kubectl 进行故障排除

在第 2 小节中使用了 Kubectl 命令行界面。第 3 小节中会使用 kubectl 获取有关 Deployment 的应用程序及环境的信息。最常见的操作可以通过以下 kubectl 命令完成:

  • kubectl get - 列出资源
  • kubectl describe - 显示有关资源的详细信息
  • kubectl logs - 从 Pod 中的容器打印日志
  • kubectl exec - 在 Pod 中的容器上执行命令

可以使用这些命令查看应用程序的部署时间、当前状态、运行位置以及配置信息。

Node 是 Kubernetes 中执行具体任务的机器,可能是虚拟机或物理机,具体取决于群集。一个 Node 上可以运行多个 Pod。

3.2 交互式教程

Step 1 检查应用的配置

先确认一下前面部署的应用是否正在运行。使用 kubectl get 命令查看存在的 Pod:

kubectl get pods

如果没有运行中的 Pod,再次执行上面命令(部署需要几秒钟的时间)。

然后,查看这个 Pod 里面有哪些容器,这些容器是通过哪些镜像构建的。使用 kubectl describe pods 命令:

kubectl describe pods

这里会看到 Pod 中容器的详情:IP 地址,使用的端口号,和 Pod 生命周期相关的事件列表。

describe 命令的输出很复杂,并且包含了许多目前还没有讲解的概念。在教程最后你会熟悉这一切。

注意:describe 命令可以获取用于大部分 Kubernetes 原语的详情:node、deployments、pods。describe 命令的输出可读性好,不适合用于脚本。

Step 2 在终端中显示应用程序

Pod 运行在一个孤立的专用网络中,需要代理才能访问它们以便调试并与之交互。为此,我们将使用 kubectl proxy 命令在第二个终端窗口中运行代理:

kubectl proxy

现在,获取 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

通过 curl 请求查看我们的应用程序的输出:

curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/

URL 是 Pod 的 API 对应的路由。

Step 3 查看容器日志

应用程序发送到 STDOUT 的任何内容都将成为 Pod 中容器的日志。使用 kubectl logs 命令检索这些日志:

kubectl logs $POD_NAME

注意:这里不需要指定容器名字,因为在我们的 Pod 中只有一个容器。

Step 4 在容器中执行命令

Pod 启动并运行后,可以直接在容器中执行命令。使用 exec 命令时需要指定 Pod 的名字作为参数。列出环境变量:

kubectl exec $POD_NAME env

这里容器的名称可以省略,因为我们在 Pod 中只有一个容器。

下面,让我们在 Pod 的容器中开始一个 bash 会话:

kubectl exec -ti $POD_NAME bash

现在,在我们运行 NodeJS 应用程序的容器中开启了会话。应用程序的源代码是 server.js 文件:

cat server.js

可以通过 curl 命令确认应用程序是否启动并在运行中:

curl localhost:8080

注意:这里是在 NodeJS 容器内执行命令,所以才可以使用 localhost。

通过 exit 命令关闭到容器的连接。

4 暴露应用到外网环境

4.1 通过 Service 暴露应用程序

Kubernetes Service 概述

Kubernetes Pod 是有 生命周期 的。当工作节点宕机时,节点上运行的 Pod 也会丢失。然后,ReplicationController 会创建新的 Pod 来动态地使集群回到所需的状态,以保持应用程序的运行。另一个例子,考虑具有 3 个副本的图像处理后端。副本是可以替代的,前端系统不应该关心后端的副本,哪怕 Pod 丢失并重新创建。也就是说,Kubernetes 集群中的每个 Pod 都具有唯一的 IP 地址,即使是同一个节点上的 Pod 也是如此,因此需要一种自动协调 Pod 切换的方式,以便应用程序持续运行。

Kubernetes 中的 Service 是一个抽象,定义了一个 Pod 的逻辑分组和一个访问这些 Pod 的策略。服务使得相关 Pod 之间建立松散耦合。就像其他 Kubernetes 对象一样,通过 YAML(首选)或 JSON 来定义 Service。Service 所针对的一组 Pod 集合通常由 LabelSelector 标签选择器来确定(请参阅下面的内容以了解为什么您可能需要规范中不包含选择器的 Service。a Service without including selector in the spec)。

虽然每个 Pod 具有唯一的 IP 地址,但是如果没有 Service,这些 IP 不会暴露到集群外部。Service 允许应用程序接收流量。通过在 ServiceSpec 中指定类型,可以以不同的方式暴露 Service:

  • ClusterIP(默认) - 将 Service 公开在集群的内部 IP 上。这种类型使服务只能从集群内访问。
  • NodePort - 使用 NAT 在集群中每个选定节点的同一端口上暴露 Service。使用 <NodeIP>:<NodePort> 使集群外部的服务可访问。ClusterIP 的超集。
  • LoadBalancer - 在当前云中创建外部负载平衡器(如果支持)并为服务分配固定的外部 IP。NodePort 的超集。
  • ExternalName - 使用任意名称(由规范中的externalName指定)通过返回具有名称的 CNAME 记录来暴露 Service。没有使用代理。需要 v1.7 或更高版本的 kube-dns。

有关不同类型 Service 的更多信息可以在 Using Source IP 教程中找到。另请参阅 用服务连接应用程序。

此外,注意,有些 Service 的用例未在 spec 规范中定义 selector。创建的 Service 如果没有 selector,就不会创建相应的 Endpoint 对象。这允许用户手动将 Service 映射到特定的端点。不使用 selector 的另一个可能性是你严格使用 type: ExternalName

Kubernetes Service 是一个抽象层,定义了 Pod 的逻辑分组,并为这一组 Pod 实现外部流量暴露,负载均衡和服务发现。

Service 和 Label

这里写图片描述

Service 通过一组 Pod 来路由流量。Service 是一个抽象层,允许 Pod 在 Kubernetes 中死亡和复制而不影响应用程序。在相关 Pod 中的发现和路由(例如应用程序中的前端和后端组件)由 Kubernetes Services 处理。

Services 使用 标签和选择器 匹配一组 Pod,这是一个允许对 Kubernetes 中的对象进行逻辑操作的分组原语(Services match a set of Pods using labels and selectors, a grouping primitive that allows logical operation on objects in Kubernetes)。标签是附加到对象的键/值对,可以以多种方式使用:

  • 指定用于开发,测试和生产的对象
  • 嵌入版本标签
  • 使用标签分类对象

这里写图片描述

可以在创建 Deployment 的同时在 kubectl 中使用 --expose 创建 Service。

标签可以在创建时或之后添加到对象,并且可以随时修改。现在让我们使用服务公开我们的应用程序并应用一些标签。

4.2 交互式教程

Step 1 创建 Service

首先确认应用是否正在运行。使用 kubectl get 命令查看存在的 Pod 及状态:

kubectl get pods

然后,列出集群当前运行的 Service:

kubectl get services
NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1        <none>        443/TCP          3m

有一个名为 Kubernetes 的 Service,在 Minikube 启动集群时会默认创建这个服务。通过 expose 命令,使用 NodePort 参数(Minikube 暂时不支持 LoadBalancer),创建新 Service 并将其暴露到外网:

kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080

再次列出集群当前运行的 Service:

kubectl get services
NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1        <none>        443/TCP          3m
kubernetes-bootcamp   NodePort    10.105.185.171   <none>        8080:32327/TCP   9s

kubernetes-bootcamp 这个 Service 已经运行了。可以看到,这个 Service 有一个唯一的 CLUSTER-IP,一个内部端口号以及一个 EXTERNAL-IP(Node 节点的 IP)。

要找出开放到外部的端口(通过 NodePort 选项)是哪个,需要运行 kubectl describe service 命令:

kubectl describe services/kubernetes-bootcamp

创建名为 NODE_PORT 的环境变量,保存分配的节点端口号:

export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
echo NODE_PORT=$NODE_PORT

现在,可以通过 curl、Node 节点的 IP 地址及暴露的端口号测试应用程序是否可以从外网访问:

curl $(minikube ip):$NODE_PORT

如果成功获取服务器的响应,则 Service 暴露成功。

Step 2: 使用标签

Deployment 自动为 Pod 创建了一个标签。使用 kubectl describe deployment 命令,可以看到标签的名称:

# kubectl describe deployment
Name:                   kubernetes-bootcamp
Namespace:              default
CreationTimestamp:      Mon, 09 Apr 2018 07:26:15 +0000
Labels:                 run=kubernetes-bootcamp
Annotations:            deployment.kubernetes.io/revision=1
Selector:               run=kubernetes-bootcamp
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  run=kubernetes-bootcamp
  Containers:
   kubernetes-bootcamp:
    Image:        gcr.io/google-samples/kubernetes-bootcamp:v1
    Port:         8080/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
OldReplicaSets:  <none>
NewReplicaSet:   kubernetes-bootcamp-5dbf48f7d4 (1/1 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  32m   deployment-controller  Scaled up replica set kubernetes-bootcamp-5dbf48f7d4 to 1

可以通过这个标签查询 Pod。使用 kubectl get pods 命令时,通过 -l 参数指定标签值:

# kubectl get pods -l run=kubernetes-bootcamp
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-5dbf48f7d4-c8jwv   1/1       Running   0          35m

查看 Service 时,也可以使用这个参数:

# kubectl get services -l run=kubernetes-bootcamp
NAME                  TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes-bootcamp   NodePort   10.105.185.171   <none>        8080:32327/TCP   32m

获取 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

可以通过 kubectl label 对象类型 对象名字 新标签 命令创建新标签:

kubectl label pod $POD_NAME app=v1

这会为我们的 Pod 应用一个新标签(这里将应用程序的版本固定到 Pod),可以使用 kubectl describe pod 命令检查:

kubectl describe pods $POD_NAME

这里会看到标签附加到了 Pod 上。现在可以使用这个新标签来查询 Pod 列表了:

kubectl get pods -l app=v1

Step 3 删除 Service

通过 kubectl delete service -l your-label 命令删除 Service。这里也可以使用标签:

kubectl delete service -l run=kubernetes-bootcamp

确认 Service 删除是否成功:

kubectl get services

这里会发现 Service 删除成功。可以通过 curl 和之前暴露的 IP 地址和端口号确认路由不再暴露到外网:

curl $(minikube ip):$NODE_PORT

这证明集群外部无法继续访问我们的应用程序了。可以通过在 Pod 内部执行 curl 来验证应用程序仍然在运行中:

kubectl exec -ti $POD_NAME curl localhost:8080

可以看到应用仍在运行。

5 伸缩应用

5.1 运行应用的多个实例

伸缩一个应用

在之前的讲解中,我们创建了一个 Deployment,然后通过一个 Service 将其暴露到外网。Deployment 只创建一个 Pod 来运行我们的应用程序。当流量增加时,我们需要扩展应用以满足用户需求。

应用的伸缩是通过改变 Deployment 中副本的数量来完成的。

可以使用 kubectl run 命令的 --replicas 参数从头开始创建具有多个实例的Deployment。

Scaling 概览图

这里写图片描述

这里写图片描述
应用的伸缩是通过改变 Deployment 中副本的数量来完成的。

扩展 Deployment 将确保创建新 Pod 并将其调度到具有可用资源的节点。收缩 Deployment 将减少 Pod 到新的期望数量。Kubernetes 还支持 Pod 的 自动缩放,但它不在本教程的范围之内。伸缩到零也是可能的,这会终止指定 Deployment 的所有 Pod。

运行应用程序的多个实例将需要一种方法将流量分配给所有这些实例。Service 具有集成的负载均衡器,可将网络流量分配给 Deployment 的所有 Pod。Service 将使用 endpoint 持续监视正在运行的 Pod,以确保流量仅发送到可用的 Pod。

应用伸缩是通过更改 Deployment 中副本的数量来完成的。

一旦运行了多个应用程序实例,就可以在不停机的情况下执行滚动更新。在下一小节中介绍会介绍。现在,转到在线终端并扩展我们的应用程序。

5.2 交互式教程

Step 1: 伸缩 Deployment

列出 Pod:

$ kubectl get pods -o wide
NAME                                   READY     STATUS    RESTARTS   AGE       IP         NODE
kubernetes-bootcamp-5c69669756-56z44   1/1       Running   0          11s       172.18.0.2   minikube

列出 Deployment:

$ kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1         1         1            1           2m

我们应该有 1 个 Pod。如果不是,请再次运行该命令。各字段的解释如下:

  • DESIRED 字段显示配置的副本数量
  • CURRENT 字段显示现在有多少副本正在运行
  • UP-TO-DATE 是已更新的副本数量,在滚动更新时,这个数字会从 0 增大到 DESIRED 字段值
  • AVAILABLE 字段显示用户实际可用的副本数量

然后,将 Deployment 扩展到 4 个副本。使用 kubectl scale 命令时,指定 Deployment 类型、名称以及所需实例的数量:

$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.extensions "kubernetes-bootcamp" scaled

再次列出可用的 Deployment:

$ kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   4         4         4            4           4m

更改已生效,现在应用程序有 4 个可用实例。接下来,看一下 Pod 的数量是否发生了变化:

$ kubectl get pods -o wide
NAME                                   READY     STATUS    RESTARTS   AGE       IP         NODE
kubernetes-bootcamp-5c69669756-4xrp6   1/1       Running   0          57s       172.18.0.6   minikube
kubernetes-bootcamp-5c69669756-56z44   1/1       Running   0          5m        172.18.0.2   minikube
kubernetes-bootcamp-5c69669756-8lccx   1/1       Running   0          57s       172.18.0.7   minikube
kubernetes-bootcamp-5c69669756-z97gr   1/1       Running   0          57s       172.18.0.5   minikube

现在有 4 个具有不同 IP 地址的 Pod。更改已在 Deployment 事件日志中注册。使用 describe 命令查看:

$ kubectl describe deployments/kubernetes-bootcamp
Name:                   kubernetes-bootcamp
Namespace:              default
CreationTimestamp:      Thu, 03 May 2018 13:21:05 +0000
Labels:                 run=kubernetes-bootcamp
Annotations:            deployment.kubernetes.io/revision=1
Selector:               run=kubernetes-bootcamp
Replicas:               4 desired | 4 updated | 4 total | 4 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  run=kubernetes-bootcamp
  Containers:
   kubernetes-bootcamp:
    Image:        gcr.io/google-samples/kubernetes-bootcamp:v1
    Port:         8080/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Progressing    True    NewReplicaSetAvailable
  Available      True    MinimumReplicasAvailable
OldReplicaSets:  <none>
NewReplicaSet:   kubernetes-bootcamp-5c69669756 (4/4 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  6m    deployment-controller  Scaled up replica set kubernetes-bootcamp-5c69669756 to 1
  Normal  ScalingReplicaSet  2m    deployment-controller  Scaled up replica set kubernetes-bootcamp-5c69669756 to 4

从这个命令的输出中也可以看到现在有 4 个副本。

Step 2: 负载均衡

检查 Service 是否对流量做了负载均衡。可以通过 describe 命令找出暴露的 IP 地址和端口:

kubectl describe services/kubernetes-bootcamp

创建名为 NODE_PORT 的环境变量保存节点的端口号:

$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
$ echo NODE_PORT=$NODE_PORT
NODE_PORT=30999

然后,通过 curl 访问暴露的 IP 地址和端口号。多次执行这个命令:

$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-j58hc | v=1

每个请求会命中不同的 Pod。这证明负载均衡生效了。

Step 3: 缩减应用

再次运行 kubectl scale 命令将 Service 缩减为 2 个副本:

$ kubectl scale deployment/kubernetes-bootcamp --replicas=2
deployment.extensions "kubernetes-bootcamp" scaled

列出 Deployment 来验证变更是否生效:

$ kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   2         2         2            2           2m

期望的副本数是 2。列出 Pod 的数量:

$ kubectl get pods -o wide
NAME                                   READY     STATUS        RESTARTS   AGEIP           NODE
kubernetes-bootcamp-5c69669756-dmbj8   1/1       Terminating   0          2m172.18.0.5   minikube
kubernetes-bootcamp-5c69669756-j58hc   1/1       Terminating   0          2m172.18.0.2   minikube
kubernetes-bootcamp-5c69669756-mvj7v   1/1       Running       0          2m172.18.0.3   minikube
kubernetes-bootcamp-5c69669756-n47zs   1/1       Running       0          2m172.18.0.4   minikube

只剩 2 个运行中的 Pod 了。

6 更新应用

6.1 执行滚动更新

更新应用

用户希望应用程序随时都可以访问,而开发者希望每天能部署几个新版本。在 Kubernetes 中通过滚动更新实现这两个目的。滚动更新使用新的实例逐个更新 Pod(而不是一次全部更新),从而实现不停机对 Deployment 的更新。新 Pod 将分配到具有可用资源的节点上。

在之前的讲解中,我们伸缩了应用程序以运行多个实例。这是执行更新而不影响应用程序可用性的要求。默认情况下,更新过程中允许不可用的 Pod 的最大数量以及可以创建的新 Pod 的最大数量为 1。这两个选项都可以配置为数字或百分比(相对于 Pods)。在 Kubernetes 中,更新是版本化的,任何 Deployment 的更新都可以恢复到以前的(稳定)版本。

滚动更新使用新的实例逐个更新 Pod(而不是一次全部更新),从而实现不停机对 Deployment 的更新。

滚动升级概览

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

与应用程序伸缩类似,如果 Deployment 暴露到外网,在更新期间 Service 会将流量负载平衡到可用的 Pod。可用的 Pod 是可以响应用户请求的应用程序的可用实例。

滚动更新允许执行以下操作:

  • 将应用程序从一个环境推到另一个环境(通过容器镜像更新)
  • 回退到以前的版本
  • 以零停机时间持续集成和持续交付应用程序

如果 Deployment 暴露到外网,在更新期间 Service 会将流量负载平衡到可用的 Pod。

在下面的交互式教程中,会将我们的应用程序更新为新版本,并执行回滚。

6.2 交互式教程

Step 1: 更新应用程序的版本

列出所有 Deployment:

$ kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   4         4         4            4           16s

列出运行中的 Pod:

$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-5c69669756-2qclp   1/1       Running   0          35s
kubernetes-bootcamp-5c69669756-btznb   1/1       Running   0          35s
kubernetes-bootcamp-5c69669756-dfjzr   1/1       Running   0          35s
kubernetes-bootcamp-5c69669756-kl225   1/1       Running   0          35s

通过对 Pod 执行 describe 命令(查看 Image 字段)查看当前应用程序的版本。

$ kubectl describe pods
Name:           kubernetes-bootcamp-5c69669756-2qclp
Namespace:      default
Node:           minikube/172.17.0.33
Start Time:     Thu, 03 May 2018 14:39:49 +0000
Labels:         pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.2
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://bd2acdb49f2d9a2e9f796065372425562818156e8f121c69b11c29c260f2f106
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 May 2018 14:39:51 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-86srb (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-86srb:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-86srb
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age              From               Message
  ----     ------                 ----             ----               -------
  Warning  FailedScheduling       1m (x2 over 1m)  default-scheduler  0/1 nodes areavailable: 1 node(s) were not ready.
  Normal   Scheduled              1m               default-scheduler  Successfully assigned kubernetes-bootcamp-5c69669756-2qclp to minikube
  Normal   SuccessfulMountVolume  1m               kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-86srb"
  Normal   Pulled                 1m               kubelet, minikube  Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal   Created                1m               kubelet, minikube  Created container
  Normal   Started                1m               kubelet, minikube  Started container


Name:           kubernetes-bootcamp-5c69669756-btznb
Namespace:      default
Node:           minikube/172.17.0.33
Start Time:     Thu, 03 May 2018 14:39:49 +0000
Labels:         pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.3
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://40dfdafb48176b77efaa6eaf3c8ed256feffd15e60743d4da51419eb3d5c9a33
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 May 2018 14:39:52 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-86srb (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-86srb:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-86srb
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age              From               Message
  ----     ------                 ----             ----               -------
  Warning  FailedScheduling       1m (x3 over 1m)  default-scheduler  0/1 nodes areavailable: 1 node(s) were not ready.
  Normal   Scheduled              1m               default-scheduler  Successfully assigned kubernetes-bootcamp-5c69669756-btznb to minikube
  Normal   SuccessfulMountVolume  1m               kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-86srb"
  Normal   Pulled                 1m               kubelet, minikube  Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal   Created                1m               kubelet, minikube  Created container
  Normal   Started                1m               kubelet, minikube  Started container


Name:           kubernetes-bootcamp-5c69669756-dfjzr
Namespace:      default
Node:           minikube/172.17.0.33
Start Time:     Thu, 03 May 2018 14:39:50 +0000
Labels:         pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.5
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://822193c72cdd69142f355c1e514b9a63246c9b29b34e8c3424d74e422dbc2461
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 May 2018 14:39:52 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-86srb (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-86srb:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-86srb
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age              From               Message
  ----     ------                 ----             ----               -------
  Warning  FailedScheduling       1m (x3 over 1m)  default-scheduler  0/1 nodes areavailable: 1 node(s) were not ready.
  Normal   Scheduled              1m               default-scheduler  Successfully assigned kubernetes-bootcamp-5c69669756-dfjzr to minikube
  Normal   SuccessfulMountVolume  1m               kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-86srb"
  Normal   Pulled                 1m               kubelet, minikube  Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal   Created                1m               kubelet, minikube  Created container
  Normal   Started                1m               kubelet, minikube  Started container


Name:           kubernetes-bootcamp-5c69669756-kl225
Namespace:      default
Node:           minikube/172.17.0.33
Start Time:     Thu, 03 May 2018 14:39:50 +0000
Labels:         pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.18.0.4
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://60f8bd1b989b701a5a51371db665886aba700839e9cf21651bc8385781f13b34
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Thu, 03 May 2018 14:39:52 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-86srb (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-86srb:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-86srb
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type     Reason                 Age              From               Message
  ----     ------                 ----             ----               -------
  Warning  FailedScheduling       1m (x3 over 1m)  default-scheduler  0/1 nodes areavailable: 1 node(s) were not ready.
  Normal   Scheduled              1m               default-scheduler  Successfully assigned kubernetes-bootcamp-5c69669756-kl225 to minikube
  Normal   SuccessfulMountVolume  1m               kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-86srb"
  Normal   Pulled                 1m               kubelet, minikube  Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal   Created                1m               kubelet, minikube  Created container
  Normal   Started                1m               kubelet, minikube  Started container

执行 set image 命令,并指定 Deployment 名称及新镜像,升级应用程序的镜像到版本 2。

$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
deployment.apps "kubernetes-bootcamp" image updated

命令通知 Deployment 为应用程序使用不同的镜像,并初始化滚动更新。检查新 Pod 的状态:

kubectl get pods

Step 2: 验证升级

首先,检查应用程序是否在运行。通过 describe service 命令找出暴露的 IP 地址和端口号:

kubectl describe services/kubernetes-bootcamp

创建名为 NODE_PORT 的环境变量,保存分配到的节点端口号:

export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
echo NODE_PORT=$NODE_PORT

然后,通过 curl 访问暴露的 IP 地址和端口号:

curl $(minikube ip):$NODE_PORT

每次请求命中不同的 Pod,且所有 Pod 都运行最新版本(v2)。

更新也可以通过 rollout status 命令来确认:

kubectl rollout status deployments/kubernetes-bootcamp

通过在 Pod 上执行 describe 命令来查看应用程序当前运行的镜像的版本号:

kubectl describe pods

查看 Image 字段,现在运行的是应用程序的版本 2。

Step 3: 回滚更新

现在执行另外一个更新,部署标记为 v10 的镜像:

kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10

查看 Deployment 的状态:

kubectl get deployments

出错了。。。没有可用的 Pod 数量。查看所有的 Pod:

kubectl get pods

针对 Pod 的 describe 命令可以提供更多信息:

kubectl describe pods

仓库中没有名为 v10 的镜像。现在要回到之前的可以正常工作的版本。使用 rollout undo 命令:

kubectl rollout undo deployments/kubernetes-bootcamp

rollout 命令将 Deployment 恢复到之前已知的状态(v2 版本的镜像)。更新是版本化的,你可以恢复到任何之前知道的 Deployment 状态。再次列出 Pods:

kubectl get pods

4 个 Pod 正在运行。再次检查部署到这些 Pod 上的镜像:

kubectl describe pods

可以看到 Deployment 使用的是稳定版本的应用程序(v2)。回滚成功了。

转载于:https://www.cnblogs.com/kika/p/10851626.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kubernetes tutorial - K8S 官方入门教程 中文翻译 的相关文章

随机推荐

  • 原来bug解决了,是这样的感觉

    终于过了 xff0c 感觉好想哭啊 xff0c 又莫名其妙的爽 xff0c 原来这就是bug 转载于 https www cnblogs com allison aichipingguo p 10018117 html
  • 闲话handle和handler

    虽然handle和handler只有一个字符之差 xff0c 但在计算机的世界里 xff0c 含义却大相径庭 1 先说说handle 北京话说 34 一边儿玩儿去 xff0c 玩勺子把儿去 34 xff0c 34 勺子把儿 34 说的就是h
  • 大数据发展前沿 期末总结复习

    其实就是简单的在网上搜了一下每个重要词条的基本概念 1 对抗学习 xff08 含Pytorch最简单的深度学习命令 xff09 生成对抗网络 xff08 GAN xff09 是非监督式学习的一种方法 xff0c 透过两个神经网络相互博弈的方
  • 出租车Jt/T 905协议与部标1078协议融合的网约车视频监控平台

    出租车 jt t 905协议 xff0c 是 jt t 808 协议的一个变种 xff0c 设计者将部标 808 协议拿过来 xff0c 并不是单纯的增加网约车相关的指令集 xff0c 而且对原有的指令如定位 0 0200 指令也进行了修改
  • 几款Git GUI客户端工具

    工欲善其事 xff0c 必先利其器 作为一名开发人员 xff0c 你不可能不知道git xff0c 无论你是开发自己的开源项目还是和团队一起进行大规模产品的开发 xff0c git都已经是源代码管理工具的首选 当然 xff0c 那些hard
  • 毕设(一)C#的百度api调用

    这个学期就要毕业了 xff0c 选了一个无人机地面站软件设计的题目 xff0c 这几天也开始着手做 xff0c 首先做了一个百度地图的调用 xff0c 这里因为是上位机的开发 xff0c 所有就不介绍Javascript的 调用方法 xff
  • tf-ros

    http wiki ros org cn tf Tutorials https www ncnynl com archives 201708 1881 html 1 广播变换 发布坐标之间的坐标关系 include lt ros ros h
  • Makefile shell subst $(1)

    MAKE 3 80 realpath 61 shell top srcdir scripts realpath sh 39 subst SQUOTE SQUOTE 1 39 以上Makefile思考好几天不得要领 xff1a 今天想通了 x
  • docker 卸载

    使用yum安装docker xff08 安装过程可以参照linux 安装docker xff09 xff0c 如需卸载docker可以按一下步骤操作 xff1a 1 查看当前docker状态 如果是运行状态则停掉 systemctl sto
  • VIN-Fusion config with Realsense D435i

    First shot Copy the launch file in package VINS Fusion to the directory of realsense2 cameara launch cp home william cat
  • 算法的5个层次

    对算法的掌握 xff0c 大致可以分为5个层次 听说 了解 理解 实现 应用 Level 1 xff1a 听说 知道算法名 知道算法功能 Leven 2 xff1a 了解 知道算法原理 自然语言描述 知道算法优缺点 Leven 3 xff1
  • elf文件下载出错问题

    现在遇到的是sof文件下载有问题 xff0c 不是对应的sof文件 在复制工程后 xff0c 可以在assignment gt setting中指定生成文件所在的文件夹 xff0c 防止sof文件的不对应 转载于 https www cnb
  • 搞定INTEL快速存储技术(用SSD硬盘做缓存加速)

    给朋友买了个联想 ideapad s400 超级本 xff0c 还真是锻炼我的 idea 啊 xff0c 原机不带 WIN7 系统 xff0c 所以只好自己动手装 WIN7 xff0c 并打开 24G SSD 硬盘做缓存 一 用常规方法 G
  • php取今天开始结束,PHP获取今天开始和结束的时间戳

    PHP获取今天开始和结束的时间戳 xff1a t 61 time 开始时间戳 start 61 mktime 0 0 0 date 34 m 34 t date 34 d 34 t date 34 Y 34 t 结束时间戳 end 61 m
  • Java中Semaphore(信号量)的使用

    Semaphore的作用 xff1a 在java中 xff0c 使用了synchronized关键字和Lock锁实现了资源的并发访问控制 xff0c 在同一时间只允许唯一了线程进入临界区访问资源 读锁除外 xff0c 这样子控制的主要目的是
  • git找回丢失的代码

    多人开发时找回丢失的代码 1 先保证所有分支的代码都已经提交并拉取到最新状态 2 最重要的是需要找到最近一条自己代码还存在的记录 xff0c 然后复制到最近的更早一条的提交记录的id xff0c 比如e36e9e76da144536c196
  • Docker容器进入的4种方式

    Docker容器进入的4种方式 在使用Docker创建了容器之后 xff0c 大家比较关心的就是如何进入该容器了 xff0c 其实进入Docker容器有好几多种方式 xff0c 这里我们就讲一下常用的几种进入Docker容器的方法 进入Do
  • HTTP Basic和Digest认证介绍与计算

    一 说明 web用户认证 xff0c 最开始是get提交 43 把用户名密码存放在客户端的cookie中的形式 xff1b 在意识到这样不安全之后逐渐演变成了post提交 43 把用户凭证放到了服务端的session中的形式 xff08 当
  • TeamViewer 的替代品 ZeroTier + NoMachine

    之前不怎么用 TeamViewer xff0c 最近用的多了 xff0c 特别好用 xff0c 有点上瘾 xff0c 在哪儿都能连家里的 RTX xff0c 太棒了 然后它就开始作了 有没有好的替代方案呢 xff1f 有人推荐向日葵 xff
  • Kubernetes tutorial - K8S 官方入门教程 中文翻译

    官方教程 xff0c 共 6 个小节 每一小节的第一部分是知识讲解 xff0c 第二部分是在线测试环境的入口 kubectl 的命令手册 原文地址 1 创建集群 1 1 使用 Minikube 创建集群 Kubernetes 集群 Kube