[k8s]k8s基础

1 使用minikube创建一个集群

1.1 kubernetes集群

Kubernetes协调一组高度可用的计算机,这些计算机连接在一起以作为一个单一单元工作。k8s提供的抽象可以把容器化的应用部署到集群上,而无需将应用指定到具体的机器上。应用必须容器化。k8s会自动负责应用容器在集群中的分布和调度。

k8s集群包含两种资源:

  • 控制平面负责协调整个集群
  • Node负责运行应用。
    • Node是一个实际的物理机或虚拟机。
    • 每个Node有kubelet,负责通控制平面通信以及管理node。
    • 每个Node还有负责处理容器运行的工具,例如containerd/CRI-O。

通过控制平面来部署应用,控制平面会负责调度应用容器在node上运行。

可以通过控制平面暴露的kubernetes API和控制平面通信。Node上的kubelet和终端用户都可以通过这种方式同控制平面通信。

1.2 通过minikube创建一个集群

1.2.1 创建一个minikube集群

1
minikube start	

1.2.2 打开Dashboard

1
2
minikube dashboard	
minikube dashboard --url

dashboard命令启用dashboard插件并在默认的网页浏览器中打开代理。你可以通过dashboard创建Kubernetes资源,如部署和服务。

通过 --url 参数,可以不自动打开dashboard,而是返回一个url。

默认情况下,dashboard只能在集群内部的虚拟网络中访问,dashboard命令创建了一个临时的代理,使dashboard可以从外部访问。

ctrl+c 可以关闭这个临时代理,但是dashboard还是在集群内部运行,后面可以重新用 dashboard 命令创建代理。

1.2.3 创建一个deployment

deployment会检查pod的状态,并且维护容器的运行,如果容器挂了,会自动重启容器。

  1. kubectl create 命令创建一个deployment负责管理pod。pod根据提供的容器镜像运行容器。

    1
    kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.39 -- /agnhost netexec --http-port=8080
  2. 查看deployment

    1
    kubectl get deployments
  3. 查看pod

    1
    kubectl get pods
  4. 查看集群事件

    1
    kubectl get events
  5. 查看kubectl配置

    1
    kubectl config view
  6. 查看pod中容器的应用日志

    1
    kubectl logs hello-node-5f76cf6ccf-br9b5

1.3 创建一个service

默认情况下,pod只能通过集群内部ip地址在集群内部访问。必须将pod作为k8s service暴露出来,才能在外部访问该pod中的容器。

  1. 将pod暴露在外部网络中

    1
    kubectl expose deployment hello-node --type=LoadBalancer --port=8080

    --type=LoadBalancer 选项表明希望将服务暴露给集群外部。

  2. 查看服务

    1
    kubectl get services
  3. 运行下列命令

    1
    minikube service hello-node

1.4 打开插件(addons)

  1. 显示目前支持的插件

    1
    minikube addons list
  2. 打开某个插件

    1
    minikube addons enable metrics-server
  3. 查看安装该插件后,创建的pod和服务

    1
    kubectl get pod,svc -n kube-system

    这条命令查看在kube-system命名空间下的所有pod和service资源的状态。

  4. 查看metrics-server的输出

    1
    kubectl top pods

    kubectl top pods 命令用于显示Kubernetes集群中各个Pod的资源使用情况,比如CPU和内存的消耗。

    • topkubectl 的一个子命令,用来实时查看集群中资源对象(如Pod或节点)的资源使用情况。
    • pods 指定了查询的对象类型是Pod。这条命令会列出所有命名空间下的Pod及其对应的资源使用情况,除非通过 -n 参数指定了特定的命名空间。

    为了使 kubectl top pods 命令能够正常工作,集群必须部署了Metric Server。且执行命令的用户需要有访问Metric Server提供的资源指标API的权限。

  5. 关闭metrics-server插件

    1
    minikube addons disable metrics-server

1.5清理

  1. 清理在集群中创建的资源

    1
    2
    kubectl delete service hello-node
    kubectl delete deployment hello-node
  2. 关闭minikube集群

    1
    minikube stop

2 使用kubectl创建一个deployment

2.1 Kubernetes Deployments

一旦有了一个运行中的Kubernetes集群,就可以在上面部署容器化应用。为此,需要创建一个Kubernetes Deployment。该部署会指示Kubernetes如何创建和更新应用实例。创建部署后,Kubernetes控制平面会调度该部署中包含的应用实例在集群的各个节点上运行。

一旦应用实例被创建,Kubernetes部署控制器会持续监控这些实例。如果托管实例的节点发生故障或被删除,部署控制器会用集群中另一个节点上的实例替换该实例。这提供了一种自我修复机制,以应对机器故障或维护。

2.2 在k8s上部署应用

可以使用Kubernetes命令行界面kubectl来创建和管理deployment。Kubectl利用Kubernetes API与集群进行交互。

当创建一个deployment时,需要指定应用的容器镜像和希望运行的副本数量。也可以后续通过更新deployment来更改这些信息。

2.3 kubectl基础

kubectl命令通用格式:kubectl action resource

这会在指定的资源(node,deployment…)上执行指定的操作(create, describe, delete…)。可以用 --help 命令来查看可能的参数(kubectl get nodes --help)。

2.4 部署一个应用

通过以下命令部署应用。需要指明deployment的名字以及应用镜像的位置。

1
kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1

这个命令会进行以下几个操作:

  • 查找合适的node来运行应用
  • 调度应用在该node上运行
  • 配置集群,当需要的时候重新调度实例运行

使用 kubectl get deployments 命令来查看所有的deployment。

2.5 查看应用

在Kubernetes内部运行的Pod位于一个私有的、隔离的网络中。默认情况下,它们只能被同一个Kubernetes集群内的其他Pod和服务看到,而不能从外部网络访问。当使用kubectl时,是通过API端点与应用程序进行交互的。

kubectl proxy命令可以创建一个代理,将通信转发到集群范围的私有网络中。代理可以通过按下Control+C终止,并且在运行时不会显示任何输出。

需要打开第二个终端窗口来运行这个代理。

1
kubectl proxy

现在已经在主机(终端)和Kubernetes集群之间建立了连接。这个代理允许从这些终端直接访问API。

可以通过代理端点查看所有这些API。例如,可以使用curl命令直接通过API查询版本:

1
curl http://localhost:8001/version

API服务器会根据Pod的名称自动为每个Pod创建一个端点,这些端点也可以通过代理访问。

首先,需要获取Pod的名称

1
kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{end}}'

你可以通过代理API访问Pod,运行以下命令:

1
curl http://localhost:8001/api/v1/namespaces/default/pods/kubernetes-bootcamp-9bc58d867-kcmfc:8080/proxy/

3 查看Pods和Nodes的信息

3.1 Pods

当创建一个deployment时,Kubernetes创建了一个Pod来承载应用实例。Pod是Kubernetes的一种抽象,代表了一组一个或多个应用程序容器(如Docker容器),以及这些容器共享的一些资源。这些资源包括:

  • 共享存储,以volume的形式提供
  • 网络,提供唯一的集群IP地址
  • 运行每个容器的信息,例如容器镜像版本或要使用的特定端口

Pod模型化了一个应用特定的“逻辑主机”,它可以包含不同的应用程序容器,这些容器之间的耦合相对紧密。Pod中的容器共享同一个IP地址和端口空间,总是共同位于一处并一同调度,并在同一个节点上以共享的上下文运行

在Kubernetes平台上,Pod是最小的部署单元。当创建一个deployment时,该deployment会创建包含容器的Pod(而不是直接创建容器)。每个Pod都绑定到它被调度的node上,并一直留在那里直到终止(根据重启策略)或删除。如果节点发生故障,相同的Pod会被调度到集群中其他可用的节点上。这样可以确保应用的高可用性和可靠性。

3.2 Nodes

Pod运行在一个Node上。Node是Kubernetes中的工作机器,可以是虚拟机也可以是物理机。每个Node都由控制平面管理。一个Node可以运行多个Pod,Kubernetes控制平面会根据node的可用资源在集群的Nodes之间调度这些Pod。

每个Kubernetes Node至少运行以下组件:

  • Kubelet:是负责Kubernetes控制平面与Node之间通信的进程;它管理运行在该机器上的Pod和容器。
  • 容器运行时(如Docker):负责从注册表中拉取容器镜像、解包容器并运行应用程序。

只有容器之间是高度耦合的并且需要共享资源(硬盘)的时候,它们才应该被规划到同一个pod中。

3.3 Troubleshooting with kubectl

最常见的操作可以通过以下kubectl命令完成:

  • kubectl get:列出资源。例如,可以用来列出Pods、Services等资源。

    1
    kubectl get pods
  • kubectl describe:显示资源的详细信息。这对于获取有关特定资源(如Pod,node,deployment)的深入信息非常有用,包括状态、事件等。

    1
    kubectl describe pod <pod-name>
  • kubectl logs:从Pod中的容器打印日志。这对于调试运行中的应用和检查错误特别有用。

    1
    kubectl logs <pod-name>
  • kubectl exec:在Pod中的容器上执行命令。这对于进入容器内部进行调试或直接操作非常有用。

    1
    kubectl exec -it <pod-name> -- /bin/sh

3.3.1 查看容器的日志

应用程序通常会将其标准输出发送到容器内的日志中。可以使用kubectl logs命令检索这些日志:

1
kubectl logs "$POD_NAME"

注意:当在Pod中只有一个容器的时候,无需指定容器名称。如果Pod中有多个容器,需要使用-c选项指定容器名称来查看特定容器的日志。

查看特定Pod中所有容器的名称

1
kubectl describe pod <pod-name> -n <namespace>

在输出的信息中,找到 Containers: 部分,这里列出了该Pod中所有容器的名称及其相关信息。

在输出结果中,会看到类似如下的部分:

1
2
3
4
5
6
7
Containers:
container-one:
Image: nginx
...
container-two:
Image: redis
...

这里的 container-onecontainer-two 就是Pod中容器的名称。

3.3.2 在容器中执行命令

可以直接在Pod启动并运行后,在容器中执行命令。

使用exec子命令,并将Pod的名称作为参数。让我们列出环境变量:

1
kubectl exec "$POD_NAME" -- env

在Pod的容器中启动一个bash会话:

1
kubectl exec -ti "$POD_NAME" -- bash

已经打开了运行应用的容器控制台。应用的源代码位于server.js文件中:

1
cat server.js

可以通过运行以下curl命令来检查应用程序是否已启动并正在运行:

1
curl http://localhost:8080

输入exit 来关闭与容器的连接

1
exit

这样就可以退出bash会话,返回到本地终端。

4 通过service来将应用暴露给外部网络

4.1 kubernetes services

在Kubernetes中,Pod是临时的,并且有其生命周期。当一个工作节点失效时,运行在其上的Pod也会丢失。这时,ReplicaSet可以根据需要动态地通过创建新的Pod来使集群回到期望的状态,以保持应用程序的持续运行。例如,考虑一个有3个副本的图像处理后端应用。这些副本是可以互换的;前端系统不应该关心后端副本的具体情况,甚至不需要知道某个Pod丢失并被重新创建的情况。然而,每个Pod在Kubernetes集群中都有一个唯一的IP地址,即使是位于同一Node上的Pod也是如此,因此需要一种方法自动协调Pod之间的变化,以确保你的应用程序继续正常运行。

Service是一个抽象概念,它定义了一组逻辑上的Pod以及访问它们的策略。Service使得互相依赖的Pod之间可以松散耦合。Service可以通过YAML或JSON进行定义。

  • 目标Pod集:通常由label selector决定(但在某些情况下,你可能希望创建一个没有选择器的Service)。

  • IP暴露问题:尽管每个Pod都有一个唯一的IP地址,但如果没有Service,这些IP地址不会暴露到集群外部。Service允许你的应用程序接收流量。

Service类型

根据你在Service的spec中指定的类型,Service可以通过不同的方式暴露:

  • ClusterIP(默认):在集群内部IP上暴露Service。这种类型使得Service只能从集群内部访问。

  • NodePort:通过NAT在集群中每个选定node的相同端口上暴露Service。这使得你可以使用<NodeIP>:<NodePort>从集群外部访问Service。它是ClusterIP的超集。

  • LoadBalancer:在当前云环境中创建一个外部负载均衡器(如果支持),并为Service分配一个固定的外部IP。它是NodePort的超集。

  • ExternalName:将Service映射到externalName字段的内容(如foo.bar.example.com)。不设置任何形式的代理。

其他注意事项

有时,你可能会遇到一些不需要在Service的spec中定义选择器的用例。一个没有选择器的Service也不会创建相应的Endpoints对象。这允许用户手动将Service映射到特定的端点。另一种可能是严格使用type: ExternalName的情况。

4.2 service和labels

在Kubernetes中,Service用于将流量路由到一组Pod。依赖Pod之间的发现和路由(例如应用中的前端和后端组件)是由Kubernetes Services处理的。

Service如何匹配Pod

Service通过使用标签(labels)选择器(selectors)来匹配一组Pod。标签和选择器是Kubernetes中的一种分组原语,允许对对象进行逻辑操作。

  • 标签(Labels):标签是附加到对象上的key/values对,可以以多种方式使用。例如:

    • 为开发、测试和生产环境指定对象。
    • 嵌入版本标签。
    • 使用tags对对象进行分类。
  • 选择器(Selectors):选择器用于定义哪些带有特定标签的Pod应属于该Service。通过这种方式,Service可以动态地适应集群的变化,如Pod的增加或删除。

4.3 实例

step 1:创建一个service

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

使用该命令创建一个NodePort类型的服务,该服务向外部暴露端口。

使用 kubectl describe services/kubernete-bootcamp 命令来查看详细信息。

可以看到向外开放的端口是30247.

接下来,可以使用 curl http:"(minikube ip)":30247 来使用服务。

注意,在windows下使用docker desktop的时候,需要配置一个minikube tunnel。通过tunnel来进行转发。

Step 2:使用Labels

deployment自动为pod分配了一个标签,可以通过 describe deployment 命令来查看。

在get命令中使用-l参数指明标签来选择相应的pod和service

1
2
kubectl get pods -l app=kubernetes-bootcamp
kubectl get services -l app=kubernetes-bootcamp

使用label命令来为对象指明新的标签。

1
kubectl label pods <POD_NAME> version=v1

Step 3:删除service

1
kubectl delete service -l app=kubernetes-bootcamp

5 运行应用的多个实例

scaling是通过修改deployment中replica的个数来实现的。

在创建deployment的时候可以通过 --replicas 参数来创建多个实例。

5.1 Scaling概述

扩展Deployment将确保创建新的Pod,并将其调度到具有可用资源的节点上。通过扩展,可以增加Pod的数量以达到新的期望状态。Kubernetes还支持Pod的自动扩展。此外,将Pod数量扩展为零也是可行的,这将终止指定Deployment的所有Pod。

运行应用程序的多个实例需要一种方式来分配流量给所有的实例。Kubernetes中的Service具备集成的负载均衡器,能够将网络流量分配给暴露的Deployment中的所有Pod。Service会持续监控运行中的Pod,确保流量仅发送到可用的Pod。

当你有多个应用程序实例在运行时,你可以执行滚动更新(Rolling Updates)而不会造成停机。滚动更新允许你逐步替换旧的Pod并启动新的Pod,确保服务的连续性。

5.2 查看ReplicaSet

要查看由Deployment创建的ReplicaSet,可以运行以下命令:

1
kubectl get rs

ReplicaSet的名字总是格式为 [DEPLOYMENT-NAME]-[RANDOM-STRING]。这里的随机字符串是随机生成的,并使用pod-template-hash作为种子。

在输出中,有两个重要的列需要注意:

  • DESIRED:显示定义的期望的应用程序副本数量。这是在创建Deployment时指定的期望状态。
  • CURRENT:显示当前实际运行的副本数量。

5.3 扩展Deployment

要手动扩展Deployment,你可以使用kubectl scale命令。例如,要将一个名为web-app的Deployment扩展到5个副本:

1
kubectl scale deployment/web-app --replicas=5

这条命令将使Kubernetes创建足够的Pod以达到指定的副本数(在这个例子中是5个)。如果当前已经有5个或更多Pod在运行,Kubernetes会相应地减少或增加Pod的数量。

5.4 自动扩展(Horizontal Pod Autoscaler)

虽然手动扩展适用于已知的工作负载,但Kubernetes也支持基于CPU利用率等指标的自动扩展(Horizontal Pod Autoscaler)。你可以在创建Deployment时配置自动扩展策略,或者稍后添加。例如,以下命令设置了一个Deployment web-app的自动扩展策略,使其副本数在1到10之间变化,根据平均CPU使用率调整:

1
kubectl autoscale deployment web-app --min=1 --max=10 --cpu-percent=80

这意味着当平均CPU使用率达到80%时,Kubernetes会自动增加Pod的数量,最多不超过10个;当负载下降时,它也会减少Pod的数量,最少保持1个Pod运行。

6 滚动更新

6.1 更新应用

滚动更新允许在不造成停机的情况下进行部署更新,其工作原理是逐步用新Pod替换当前的Pod。新Pod被调度到有可用资源的节点上,Kubernetes会等待这些新Pod启动后再移除旧的Pod。

滚动更新的必要条件:应用程序在集群中有多个运行实例。

默认情况下,更新过程中不可用的最大Pod数量和可以创建的新Pod最大数量均为1。这两个选项都可以配置为具体的数字或比例(的Pod)。在Kubernetes中,更新是具有版本控制的,任何部署更新都可以回滚到之前的(稳定)版本。

6.2 滚动更新概述

更新前

更新中

更新中

更新后

类似于应用程序扩展,如果一个部署被公开暴露,那么在更新期间,服务将仅向可用的Pod分发流量。

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

  • 通过容器镜像更新将应用程序从一个环境升级到另一个环境
  • 回滚到之前的版本
  • 实现应用的持续集成和持续交付,并且达到零停机时间

6.3 更新应用版本

首先查看更新前的镜像版本(kubectl describe pods

要将应用程序的镜像更新到第2版,可以使用set image子命令,随后跟上deployment名称和新的镜像版本:

1
kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=docker.io/jocatalin/kubernetes-bootcamp:v2

此命令通知deployment使用新版本的镜像进行应用更新,并启动了一个滚动更新。可以通过get pods子命令检查新Pod的状态,并查看旧Pod正在终止:

1
kubectl get pods

6.4 验证更新

1
curl http://"$(minikube ip):$NODE_PORT"

每次运行curl命令时,都会访问到不同的Pod。请注意,现在所有Pod都在运行最新版本(v2)。

也可以通过运行rollout status子命令来确认更新状态:

1
kubectl rollout status deployments/kubernetes-bootcamp

要查看应用程序当前的镜像版本,可以运行describe pods子命令:

1
kubectl describe pods

在输出的镜像字段中,确认正在运行的是最新的镜像版本(v2)。

6.5 回滚更新

让我们执行另一次更新,并尝试部署一个标记为v10的镜像:

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

使用get deployments查看部署的状态:

1
kubectl get deployments

注意,输出中没有列出期望的可用Pod数量。运行get pods子命令列出所有Pod:

1
kubectl get pods

注意到一些Pod的状态为ImagePullBackOff。

为了更深入地了解问题,运行describe pods子命令:

1
kubectl describe pods

在受影响Pod的输出事件部分中,注意到v10镜像版本在仓库中不存在。

要回滚部署到最后一个正常工作的版本,使用rollout undo子命令:

1
kubectl rollout undo deployments/kubernetes-bootcamp

rollout undo命令将部署恢复到之前的已知状态(即镜像的v2版本)。更新是版本化的,可以回滚到Deployment的任何之前已知的状态。

再次使用get pods子命令列出Pod:

1
kubectl get pods

要检查正在运行的Pod上部署的镜像,使用describe pods子命令:

1
kubectl describe pods

现在,Deployment再次使用应用程序的一个稳定版本(v2)。回滚成功。

记得清理本地集群:

1
kubectl delete deployments/kubernetes-bootcamp services/kubernetes-bootcamp

[k8s]k8s基础
https://erlsrnby04.github.io/2025/03/15/k8s-k8s基础/
作者
ErlsrnBy04
发布于
2025年3月15日
许可协议