在 Kubernetes 上部署应用程序

KubernetesBeginner
立即练习

介绍

在本实验中,你将学习如何在 Kubernetes 集群上部署应用程序。我们将从使用 Minikube 设置 Kubernetes 环境开始。然后,你将探索 essential kubectl 命令来与你的集群交互并管理 Kubernetes 资源。接下来,你将创建一个简单的 YAML manifest 文件,将其应用到你的集群,并检查部署的状态。最后,你将学习如何使用 kubectl proxy 访问你已部署的应用程序。

本实验将涵盖基础的 Kubernetes 技能,包括集群设置、基本资源管理和应用程序部署。通过完成本实验,你将对如何使用 Kubernetes 和部署自己的应用程序有扎实的理解。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 82%。获得了学习者 97% 的好评率。

启动 Kubernetes 集群

在此步骤中,我们将使用 Minikube 启动一个 Kubernetes 集群。Minikube 是一个非常适合开发和学习 Kubernetes 的工具,因为它允许你在虚拟化环境中运行一个单节点 Kubernetes 集群。然后,我们将验证集群是否正常运行并已准备好使用。

首先,打开你的终端。你将在这里输入命令与你的计算机进行交互。要启动 Minikube 集群,请键入以下命令并按 Enter:

minikube start

此命令将启动创建和启动你的 Kubernetes 集群的过程。Minikube 将下载必要的组件并配置你的集群。当 Minikube 启动时,你将在终端中看到输出。以下是输出可能样子的示例:

😄  minikube v1.29.0 on Ubuntu 22.04
✨  Automatically selected the docker driver
📌  Using Docker driver with root permissions
🔥  Creating kubernetes in kubernetes cluster
🔄  Restarting existing kubernetes cluster
🐳  Preparing Kubernetes v1.26.1 on Docker 20.10.23 ...
🚀  Launching Kubernetes ...
🌟  Enabling addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace

Minikube 启动后,让我们验证它是否正在运行以及 Kubernetes 集群是否已准备就绪。依次运行以下命令,在每个命令后按 Enter:

minikube status
kubectl get nodes

minikube status 命令将告诉你 Minikube 本身的状态。kubectl get nodes 命令将与你的 Kubernetes 集群通信,并检索有关你集群中节点(计算机)的信息。由于 Minikube 是一个单节点集群,你应该会看到列出一个节点。

以下是你可能看到的输出示例:

minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

NAME       STATUS   ROLES           AGE   VERSION
minikube   Ready    control-plane   1m    v1.26.1

让我们分解一下这些输出告诉我们的信息:

  1. minikube 状态显示 hostkubeletapiserverRunning。这表明 Minikube 的核心组件正在正常运行。
  2. kubectl get nodes 显示一个名为 minikube 的节点,其 STATUSReadyReady 表示该节点已准备好运行应用程序。ROLES 下的 control-plane 表明该节点正在作为 Kubernetes 集群的控制平面,负责管理和编排集群。

这些命令确认了以下几点:

  1. Minikube 正在虚拟化环境中运行。
  2. Kubernetes 集群已由 Minikube 创建和配置。
  3. Kubernetes 集群处于 Ready 状态,已准备好使用。
  4. 你拥有一个单节点 Kubernetes 集群,其中 minikube 节点充当控制平面。

学习基础 kubectl 命令和语法

在此步骤中,你将探索基础的 kubectl 命令。kubectl 是允许你与 Kubernetes 集群交互的命令行工具。它是管理 Kubernetes 资源的关键。我们将演示如何使用 kubectl 来查看资源并理解基本的 Kubernetes 对象管理。

让我们从探索 Kubernetes 集群中的命名空间(namespaces)开始。命名空间是组织 Kubernetes 资源的一种方式。默认情况下,Kubernetes 集群包含多个用于系统组件和用户资源的命名空间。要查看命名空间列表,请运行以下命令:

kubectl get namespaces

此命令将列出你集群中所有可用的命名空间。示例输出:

NAME              STATUS   AGE
default           Active   10m
kube-node-lease   Active   10m
kube-public       Active   10m
kube-system       Active   10m

你通常会看到至少这些默认命名空间:

  • default: 如果未指定其他命名空间,则为用户创建资源的默认命名空间。
  • kube-node-lease: 用于节点租约,这有助于控制平面跟踪节点健康状况。
  • kube-public: 用于应公开访问的资源(尽管很少用于敏感信息)。
  • kube-system: 包含系统级资源,例如核心 Kubernetes 组件。

接下来,让我们查看在 kube-system 命名空间中运行的系统组件。许多核心 Kubernetes 组件作为 Pod 在此命名空间中运行。要查看特定命名空间中的 Pod,请使用 -n--namespace 标志,后跟命名空间名称。运行以下命令以查看 kube-system 命名空间中的 Pod:

kubectl get pods -n kube-system

此命令将列出在 kube-system 命名空间中运行的所有 Pod。示例输出:

NAME                               READY   STATUS    RESTARTS   AGE
coredns-787d4945fb-j8rhx           1/1     Running   0          15m
etcd-minikube                       1/1     Running   0          15m
kube-apiserver-minikube             1/1     Running   0          15m
kube-controller-manager-minikube    1/1     Running   0          15m
kube-proxy-xb9rz                    1/1     Running   0          15m
kube-scheduler-minikube             1/1     Running   0          15m
storage-provisioner                 1/1     Running   0          15m

此输出显示了 Pod 的名称、它们的 READY 状态(Pod 中有多少容器已准备好相对于总数)、它们的 STATUS(例如 Running)、它们 RESTARTED 的次数以及它们的 AGE。这些是使 Kubernetes 正常工作的基本组件。

现在,让我们探索一些基本的 kubectl 命令模式。kubectl 命令的通用语法是:

kubectl [command] [TYPE] [NAME] [flags]

让我们分解一下:

  • kubectl: 命令行工具本身。
  • [command]: 指定你想要执行的操作。常用命令包括:
    • get: 显示一个或多个资源。
    • describe: 显示关于特定资源的详细信息。
    • create: 创建一个新资源。
    • delete: 删除资源。
    • apply: 将配置应用于资源。我们稍后会经常使用它。
  • [TYPE]: 指定你想要交互的 Kubernetes 资源类型。常用资源类型包括:
    • pods: Kubernetes 中最小的可部署单元。
    • deployments: 管理 Pod 集合以进行扩展和更新。
    • services: 暴露运行在 Pod 中的应用程序。
    • nodes: Kubernetes 集群中的工作节点。
    • namespaces: 资源的逻辑分组。
  • [NAME]: 特定资源的名称。这是可选的;如果你省略名称,kubectl 将操作指定类型的所有资源。
  • [flags]: 可选标志,用于修改命令的行为(例如,-n <namespace>-o wide)。

让我们看一些例子:

## 获取默认命名空间中的所有资源
kubectl get all

## 描述特定资源类型('minikube' 节点)
kubectl describe nodes minikube

kubectl get all 命令将检索 default 命名空间中所有资源类型(services、deployments、pods 等)的信息。示例输出可能如下所示:

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   20m

这表明在 default 命名空间中,我们有一个名为 kubernetesservice

kubectl describe nodes minikube 命令将提供关于 minikube 节点的大量详细信息,包括其状态、容量、地址等。这有助于理解你的节点的状态和配置。

这些命令可以帮助你:

  1. 查看 Kubernetes 集群中的资源。
  2. 获取有关集群组件及其当前状态的详细信息。
  3. 理解 kubectl 的基本命令结构和语法。

创建一个简单的 YAML Manifest

在你创建第一个 YAML manifest 之前,理解你将要使用的关键 Kubernetes 对象非常重要。这些对象是在 Kubernetes 中管理和编排应用程序的构建块。

理解 Kubernetes 对象

  • Pod: Kubernetes 中最基本 的单元。一个 Pod 就像一个盒子,可以包含一个或多个容器。这些容器在 Pod 中共享相同的网络和存储。将 Pod 视为代表你应用程序的单个实例。
  • Deployment: Deployment 用于管理 Pod。它们确保所需数量的 Pod 副本始终在运行。如果一个 Pod 失败,Deployment 会自动替换它。Deployment 还以可控的方式处理应用程序的更新,例如滚动更新。
  • Service: Service 提供了一种稳定 的方式来访问运行在 Pod 中的应用程序。由于 Pod 可以被创建和销毁,它们的 IP 地址可能会发生变化。Service 提供了一个固定的 IP 地址和 DNS 名称,始终指向它管理的 Pod 集合。这使得你的应用程序的其他部分或外部用户能够可靠地访问你的应用程序,而无需跟踪单个 Pod 的 IP。

下面是一个图示,说明了这些对象之间的关系:

graph TD; A[Deployment] -->|Manages| B[Pods] B -->|Contains| C[Containers] B -->|Communicates via| D[Services] D -->|Exposes| E[External Clients]

理解这些对象至关重要,因为你将使用 YAML manifest 来定义它们的期望状态和配置。

YAML Manifest 概述

Kubernetes 中的 YAML manifest 是一个用 YAML 格式编写的文件,它描述了你想要创建或管理的 Kubernetes 对象。YAML 是一种人类可读的数据序列化语言。在 Kubernetes manifest 中使用 YAML 有几个优点:

  1. 声明式管理: 你在 YAML 文件中描述资源的 期望状态(例如,“我希望我的应用程序运行 3 个副本”)。然后 Kubernetes 会努力使实际状态与你的期望状态匹配。这被称为声明式管理。
  2. 版本控制: YAML 文件是基于文本的,可以轻松地存储在 Git 等版本控制系统中。这允许你随着时间的推移跟踪 Kubernetes 配置的更改,回滚到以前的配置,并与他人协作。
  3. 可重用性和可移植性: 你可以在不同的环境(开发、测试、生产)中重用 YAML manifest,只需进行少量更改。这使得你的部署更加一致和可重现。

现在你已经理解了 Kubernetes 对象和 YAML manifest 的基础知识,你就可以创建你的第一个 manifest 了。

创建一个 YAML Manifest

首先,导航到你的项目目录。假设你的主目录(~)下有一个 project 目录。如果还没有,请立即使用 mkdir project 创建它。然后,使用 cd project 更改当前目录:

cd ~/project

接下来,创建一个新目录来存储你的 Kubernetes manifest。我们将其命名为 k8s-manifests。使用 mkdir 命令创建目录,然后使用 cd 进入该目录:

mkdir -p k8s-manifests
cd k8s-manifests

现在,你将创建你的第一个 YAML manifest 文件。让我们从一个简单的 NGINX Pod manifest 开始。NGINX 是一个流行的 Web 服务器。我们将创建一个运行单个 NGINX 容器的 Pod。使用 nano 文本编辑器创建一个名为 nginx-pod.yaml 的文件:

nano nginx-pod.yaml

nano 是一个在你的终端中运行的简单文本编辑器。当 nano 打开后,将以下内容粘贴到文件中:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
    - name: nginx
      image: nginx:latest
      ports:
        - containerPort: 80

让我们理解这个 YAML manifest 的每个部分:

  • apiVersion: v1: 指定用于创建此对象的 Kubernetes API 版本。v1 是核心 API 组,用于 Pod、Service 和 Namespace 等基本对象。
  • kind: Pod: 表明你正在定义一个 Pod 资源。
  • metadata:: 包含有关 Pod 的数据,例如其名称和标签。
    • name: nginx-pod: 将 Pod 的名称设置为 nginx-pod。这就是你将在 Kubernetes 中引用此 Pod 的方式。
    • labels:: 标签是附加到对象的键值对。它们用于组织和选择对象子集。在这里,我们为这个 Pod 添加了一个 app: nginx 标签。
  • spec:: 描述 Pod 的期望状态。
    • containers:: 要在 Pod 中运行的容器列表。在这种情况下,我们只有一个容器。
      • - name: nginx: 将容器的名称设置为 nginx
      • image: nginx:latest: 指定要使用的容器镜像。nginx:latest 指的是 Docker Hub 中 NGINX Docker 镜像的最新版本。
      • ports:: 此容器将公开的端口列表。
        • - containerPort: 80: 指定容器将公开端口 80。端口 80 是标准的 HTTP 端口。

粘贴内容后,保存文件并退出 nano。为此,请按 Ctrl+X(退出),然后键入 Y(表示保存),最后按 Enter 确认文件名并保存。

现在你已经创建了 nginx-pod.yaml 文件,你需要将其应用到你的 Kubernetes 集群以创建 Pod。使用 kubectl apply 命令和 -f 标志,该标志指定包含 manifest 的文件:

kubectl apply -f nginx-pod.yaml

此命令将 manifest 发送到你的 Kubernetes 集群,Kubernetes 将按照定义创建 Pod。你应该会看到类似以下的输出:

pod/nginx-pod created

要验证 Pod 是否已创建并正在运行,请使用 kubectl get pods 命令。这将列出默认命名空间中的所有 Pod。你也可以使用 kubectl describe pod nginx-pod 来获取 nginx-pod 的详细信息。运行这些命令:

kubectl get pods
kubectl describe pod nginx-pod

kubectl get pods 的示例输出:

NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          1m

此输出显示 nginx-podREADY(1 个容器中有 1 个已准备好)并且其 STATUSRunning。这意味着你的 NGINX Pod 已成功创建并正在运行。

现在,让我们创建一个更复杂资源的 manifest:一个 Deployment。Deployment 将管理一组 Pod,确保所需数量的副本正在运行。使用 nano 创建一个名为 nginx-deployment.yaml 的新文件:

nano nginx-deployment.yaml

将以下内容粘贴到 nginx-deployment.yaml 中:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80

让我们重点介绍与 nginx-pod.yaml manifest 相比的关键区别和新增部分:

  • apiVersion: apps/v1: 对于 Deployment,你使用 apps/v1 API 版本,它是 apps API 组的一部分,用于处理更高级别的应用程序管理资源。
  • kind: Deployment: 表明你正在定义一个 Deployment 资源。
  • spec:: Deployment 的 spec 部分更复杂,因为它定义了 Deployment 如何管理 Pod。
    • replicas: 3: 这是新的。它指定你希望运行 3 个副本(副本)的 Pod。Deployment 将确保始终有 3 个 Pod 符合 template 中定义的标准。
    • selector:: Deployment 使用选择器来识别它应该管理哪些 Pod。
      • matchLabels:: 定义 Pod 必须具有的标签才能被此 Deployment 选择。在这里,它选择具有 app: nginx 标签的 Pod。
    • template:: template 定义了 Deployment 将用于创建新 Pod 的 Pod 规范。它本质上与我们 nginx-pod.yaml 示例中的 Pod 定义相同,包括 metadata.labelsspec.containers重要提示: 此处 template.metadata.labels 中定义的标签必须与 selector.matchLabels 匹配,以便 Deployment 可以管理这些 Pod。

保存并退出 nano(Ctrl+X,Y,Enter)。

现在,将此 Deployment manifest 应用到你的集群:

kubectl apply -f nginx-deployment.yaml

你应该会看到类似以下的输出:

deployment.apps/nginx-deployment created

验证 Deployment 及其创建的 Pod。使用 kubectl get deployments 检查 Deployment 状态,并使用 kubectl get pods 查看 Pod。

kubectl get deployments
kubectl get pods

示例输出:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           1m

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-xxx-yyy            1/1     Running   0          1m
nginx-deployment-xxx-zzz            1/1     Running   0          1m
nginx-deployment-xxx-www            1/1     Running   0          1m
  • kubectl get deployments 显示 nginx-deploymentREADY 为 3/3,UP-TO-DATE 为 3,AVAILABLE 为 3。这意味着 Deployment 已成功创建并正在管理 3 个 Pod,并且所有这些 Pod 都已准备好并可用。
  • kubectl get pods 现在列出了三个名称以 nginx-deployment- 开头的 Pod。这些是由你的 nginx-deployment 创建和管理的 Pod。

应用 YAML Manifest

在此步骤中,你将更详细地探索 kubectl apply 命令,并学习应用 Kubernetes manifest 的不同方法。基于上一步的 YAML 文件,我们将演示应用 manifest 的各种技术。

首先,请确保你位于正确的目录:

cd ~/project/k8s-manifests

让我们创建一个新的子目录来进一步组织我们的 manifest。创建一个名为 manifests 的目录并进入该目录:

mkdir -p manifests
cd manifests

现在,让我们创建一个包含 Deployment 和 Service 的简单 Web 应用程序的 manifest,所有内容都在一个文件中。使用 nano 创建一个名为 web-app.yaml 的新文件:

nano web-app.yaml

将以下内容添加到 web-app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:alpine
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 80

此 manifest 在单个文件中定义了两个 Kubernetes 资源:一个 Deployment 和一个 Service。--- 分隔符用于区分它们。让我们分解一下新增的内容:

  • 单个文件中的多个资源: web-app.yaml 文件现在包含两个独立的 Kubernetes 资源定义:一个 Deployment 和一个 Service。--- 分隔符用于区分它们。
  • kind: Service: 这定义了一个 Service 资源。
    • spec.selector.app: web: 此 Service 将定位具有 app: web 标签的 Pod。这与我们为 web-app Deployment 创建的 Pod 设置的标签匹配。
    • spec.type: ClusterIP: 将服务类型指定为 ClusterIP。这意味着该服务将在集群内的内部 IP 地址上公开,通常用于集群内服务之间的通信。
    • spec.ports: 定义服务如何将端口映射到目标 Pod。
      • port: 80: 你将访问的服务本身的端口。
      • targetPort: 80: 服务将流量转发到的目标 Pod 上的端口。

现在,让我们使用不同的方法应用此 manifest。

方法 1:应用整个文件

这是应用 manifest 最常见的方式。使用 kubectl apply -f 后跟文件名:

kubectl apply -f web-app.yaml

此命令将创建 web-app.yaml 中定义的 Deployment 和 Service。你应该会看到类似以下的输出:

deployment.apps/web-app created
service/web-service created

方法 2:从目录应用

你可以一次性应用目录中的所有 manifest。如果你在 manifests 目录中有多个 manifest 文件,你可以通过指定目录而不是特定文件来应用所有文件:

kubectl apply -f .

. 代表当前目录。kubectl 将在此目录中查找 YAML 文件并应用所有文件。当你将 manifest 组织到目录中的多个文件中时,这非常有用。

方法 3:从 URL 应用(可选)

kubectl apply 也可以直接从 URL 应用 manifest。这对于快速部署在线托管的示例应用程序或配置非常有用。例如,你可以从 Kubernetes 示例存储库部署 Redis master Deployment:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/redis-master-deployment.yaml

这将从 URL 下载 manifest 并将其应用到你的集群。注意:从不受信任的 URL 应用 manifest 时要小心,因为它们可能会修改你的集群。

让我们探索 kubectl apply 的一些附加选项。

Dry Run(试运行)

你可以使用 --dry-run=client 标志来模拟应用 manifest,而无需实际更改集群。这对于检查 manifest 是否有效以及查看将创建或修改哪些资源非常有用:

kubectl apply -f web-app.yaml --dry-run=client

此命令将输出 将要 创建或更改的内容,但实际上不会将更改应用到你的集群。

Verbose Output(详细输出)

为了获得 kubectl apply 的更详细输出,你可以使用 -v 标志后跟一个详细级别(例如 -v=7)。更高的详细级别提供更多信息,这对于调试很有帮助:

kubectl apply -f web-app.yaml -v=7

这将打印更多关于正在进行的 API 请求和 manifest 处理的信息。

通过应用 web-app.yaml 来验证创建的资源。使用 kubectl get deploymentskubectl get services 来列出集群中的 Deployment 和 Service:

## 列出 deployments
kubectl get deployments

## 列出 services
kubectl get services

## 描述 deployment 以查看更多详细信息
kubectl describe deployment web-app

kubectl get deployments 的示例输出:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           3m33s
redis-master       0/1     1            0           23s
web-app            2/2     2            2           42s

kubectl get services 的示例输出:

NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes    ClusterIP   10.96.0.1       <none>        443/TCP   8m28s
web-service   ClusterIP   10.106.220.33   <none>        80/TCP    46s

请注意,现在你有一个 web-app Deployment,其 READY 副本数为 2/2,以及一个类型为 ClusterIPweb-service

让我们简要讨论 Kubernetes 中声明式管理和命令式管理之间的区别,特别是在 kubectl applykubectl create 的上下文中。

  • kubectl apply: 使用声明式方法。你在 manifest 文件中定义期望状态,而 kubectl apply 会尝试实现该状态。如果你多次运行具有相同 manifest 的 kubectl apply,只有当 manifest 中的期望状态与集群中的当前状态存在差异时,Kubernetes 才会进行更改。kubectl apply 通常推荐用于管理 Kubernetes 资源,因为它更健壮且易于随时间推移管理更改。它会跟踪你资源的配置,并允许进行增量更新。
  • kubectl create: 使用命令式方法。你直接指示 Kubernetes 创建一个资源。如果你尝试为已存在的资源运行 kubectl create,通常会导致错误。与 kubectl apply 相比,kubectl create 在管理更新和更改方面灵活性较低。

在大多数情况下,尤其是在管理应用程序部署时,kubectl apply 是首选且推荐的方法,因为它具有声明性,并且在处理更新和配置管理方面表现更好。

验证 Deployment 状态

在此步骤中,你将学习如何使用各种 kubectl 命令来检查和验证 Kubernetes Deployment 和其他资源的状 态。你将探索收集有关正在运行的应用程序及其在 Kubernetes 集群中健康状况信息的不同方法。

首先,请确保你位于项目中的 manifests 目录:

cd ~/project/k8s-manifests/manifests

让我们开始列出当前命名空间(除非你已更改,否则为 default)中的所有 Deployment。使用 kubectl get deployments

kubectl get deployments

此命令提供了 Deployment 的简洁概览。示例输出:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           4m44s
redis-master       1/1     1            1           94s
web-app            2/2     2            2           113s

以下是每列的含义:

  • NAME: Deployment 的名称。
  • READY: 显示就绪副本的数量与期望副本的数量(例如,3/3 表示 3 个期望的副本已就绪)。
  • UP-TO-DATE: 指示有多少副本已更新到最新的期望状态。
  • AVAILABLE: 显示当前有多少副本可用于处理流量。
  • AGE: Deployment 运行了多长时间。

要以更宽的格式获取更详细的信息,你可以将 -o wide 标志与 kubectl get deployments 一起使用:

kubectl get deployments -o wide

示例输出:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                      SELECTOR
nginx-deployment   3/3     3            3           4m58s   nginx        nginx:latest                app=nginx
redis-master       1/1     1            1           108s    master       registry.k8s.io/redis:e2e   app=redis,role=master,tier=backend
web-app            2/2     2            2           2m7s    web          nginx:alpine                app=web

-o wide 输出包含 CONTAINERSIMAGESSELECTOR 等附加列,提供了有关 Deployment 的更多上下文信息。

要检查特定 Deployment 所属的 Pod,你可以使用标签。请记住,在我们 web-app Deployment manifest 中,我们为 Pod 设置了 app: web 标签。你可以使用此标签通过 kubectl get pods -l <label_selector> 过滤 Pod。要查看与 web-app Deployment 关联的 Pod,请运行:

kubectl get pods -l app=web

示例输出:

NAME                      READY   STATUS    RESTARTS   AGE
web-app-xxx-yyy           1/1     Running   0          10m
web-app-xxx-zzz           1/1     Running   0          10m

这将列出匹配标签选择器 app=web 的 Pod,这些 Pod 是由 web-app Deployment 管理的。

要获取特定 Deployment 的详细信息,请使用 kubectl describe deployment <deployment_name>。让我们描述一下 web-app Deployment:

kubectl describe deployment web-app

kubectl describe 提供有关 Deployment 的大量信息,包括:

  • Name, Namespace, CreationTimestamp, Labels, Annotations: Deployment 的基本元数据。
  • Selector: 用于标识此 Deployment 管理的 Pod 的标签选择器。
  • Replicas: 期望的、已更新的、总共的、可用的和不可用的副本计数。
  • StrategyType, RollingUpdateStrategy: 有关更新策略的详细信息(例如,RollingUpdate)。
  • Pod Template: 用于为此 Deployment 创建 Pod 的规范。
  • Conditions: 指示 Deployment 状态的条件(例如,AvailableProgressing)。
  • Events: 与 Deployment 相关的事件列表,这对于故障排除很有帮助。

查看 describe 输出中的 ConditionsEvents 部分。如果你的 Deployment 存在问题,这些部分通常会提供线索。例如,如果 Deployment 未变为 AvailableEvents 可能会显示与镜像拉取、Pod 创建失败等相关的错误。

要检查 Service 的状态,你可以使用类似的命令。首先,列出所有 Service:

kubectl get services

示例输出:

NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes    ClusterIP   10.96.0.1       <none>        443/TCP   10m
web-service   ClusterIP   10.106.220.33   <none>        80/TCP    2m47s

这会显示 web-service 及其 TYPE(在此情况下为 ClusterIP)、CLUSTER-IP 和公开的 PORT(S)

要获取 Service 的更多详细信息,请使用 kubectl describe service <service_name>

kubectl describe service web-service

describe service 输出包括:

  • Name, Namespace, Labels, Annotations: 基本元数据。
  • Selector: 用于标识目标 Pod 的标签选择器。
  • Type: Service 类型(在此情况下为 ClusterIP)。
  • IP, IPs: 分配给 Service 的集群 IP 地址。
  • Port, TargetPort: 为 Service 定义的端口映射。
  • Endpoints: 显示当前支持此 Service 的 Pod 的 IP 地址和端口。这非常重要。如果你没有看到任何端点,则意味着 Service 未正确连接到任何 Pod,可能是由于选择器不匹配。
  • Session Affinity, Events: 其他 Service 配置和事件。

在验证 Deployment 状态时,关键要查找的是:

  • Deployment READY 状态: 确保它显示了期望的副本数量(例如,web-app2/2)。
  • Pod STATUS: 所有 Pod 都应处于 Running 状态。
  • Service Endpoints: 检查 Service 是否有端点,并且它们是否对应于你的运行 Pod 的 IP 地址。如果没有端点,请排查 Service 的选择器和 Pod 标签。
  • 检查警告或错误: 查看 kubectl describe deployment <deployment_name>kubectl describe service <service_name> 的输出,查找 Events 部分中的任何异常情况或错误。

通过使用这些 kubectl 命令,你可以有效地监控和验证 Kubernetes 中 Deployment 和 Service 的状态,确保你的应用程序按预期运行。

使用 kubectl proxy 访问应用程序

在此步骤中,你将学习如何使用 kubectl proxy 访问你的 Kubernetes 应用程序。kubectl proxy 创建一个到 Kubernetes API 服务器的安全代理连接,允许你从当前环境访问集群服务和 Pod。这对于开发和调试非常有用,特别是当你想要访问未向外部公开的服务时。

首先,请确保你位于项目目录中:

cd ~/project/k8s-manifests/manifests

在后台启动 kubectl proxy。此命令将在单独的进程中运行代理,允许你继续使用终端。

kubectl proxy --port=8080 &

命令末尾的 & 会将其在后台运行。你应该会看到类似以下的输出:

Starting to serve on 127.0.0.1:8080

如果运行此命令后终端似乎挂起,你可能需要按一次 Ctrl+C 返回到命令提示符。代理应该仍在后台运行。

现在,让我们找到属于你的 web-app Deployment 的 Pod 名称。你可以再次使用 kubectl get pods -l app=web

## 获取 'web-app' 的 Pod 名称
kubectl get pods -l app=web

示例输出:

NAME                      READY   STATUS    RESTARTS   AGE
web-app-xxx-yyy           1/1     Running   0          20m
web-app-xxx-zzz           1/1     Running   0          20m

记下一个 Pod 的名称,例如 web-app-xxx-yyy。你将使用此 Pod 名称来构建 API 路径以访问该 Pod 中运行的 NGINX Web 服务器。

可以通过特定路径访问 Kubernetes API 资源。要通过 kubectl proxy 访问 Pod,你需要构建一个类似以下的 URL:

http://localhost:8080/api/v1/namespaces/<namespace>/pods/<pod_name>/proxy/

让我们分解这个 URL:

  • http://localhost:8080: kubectl proxy 运行的地址。默认情况下,它在你的当前环境中监听端口 8080。
  • /api/v1: 指定 Kubernetes API 版本(v1)。
  • /namespaces/<namespace>: 你的 Pod 运行的命名空间。在我们的例子中,它是 default
  • /pods/<pod_name>: 你要访问的 Pod 的名称。将 <pod_name> 替换为你的 Pod 的实际名称(例如,web-app-xxx-yyy)。
  • /proxy/: 指示你要代理到该 Pod 的连接。

为了方便在 URL 中使用 Pod 名称,让我们将第一个 Pod 的名称存储在一个 shell 变量中。运行此命令,它使用 kubectl get podsjsonpath 来提取带有标签 app=web 的第一个 Pod 的名称:

## 获取带有标签 'app=web' 的第一个 Pod 的名称
POD_NAME=$(kubectl get pods -l app=web -o jsonpath='{.items[0].metadata.name}')
echo $POD_NAME ## 可选:打印 Pod 名称以进行验证

现在,你可以在 curl 命令中使用 $POD_NAME 变量来访问你的 Pod 通过代理提供的 NGINX 默认页面。使用 curl 向代理 URL 发送 HTTP 请求。在 URL 中将 ${POD_NAME} 替换为我们刚刚设置的变量:

curl http://localhost:8080/api/v1/namespaces/default/pods/${POD_NAME}/proxy/

如果一切正常,此命令应返回 NGINX 默认欢迎页面的 HTML 内容。示例输出将是 HTML 内容,开头为:

<!doctype html>
<html>
  <head>
    <title>Welcome to nginx!</title>
    ...
  </head>
  <body>
    <h1>Welcome to nginx!</h1>
    ...
  </body>
</html>

此输出确认你已通过 kubectl proxy 成功访问了运行在你 Pod 中的 NGINX Web 服务器。

让我们探索一下使用 kubectl proxy 可以做的更多事情。

通过代理列出默认命名空间中的所有 Pod

你可以直接通过代理访问 Kubernetes API。例如,要列出 default 命名空间中的所有 Pod,你可以使用此 URL:

curl http://localhost:8080/api/v1/namespaces/default/pods/

这将返回一个 JSON 响应,其中包含 default 命名空间中所有 Pod 的信息。

通过代理获取特定 Pod 的详细信息

要获取特定 Pod 的详细信息(类似于 kubectl describe pod),你可以直接访问 Pod 的 API 端点:

curl http://localhost:8080/api/v1/namespaces/default/pods/${POD_NAME}

这将返回一个 JSON 响应,其中包含指定 Pod 的详细信息。

停止 kubectl proxy

当你完成使用 kubectl proxy 后,你应该停止它。由于我们是在后台启动它的,你需要找到它的进程 ID (PID) 并终止它。你可以使用 jobs 命令列出后台进程:

jobs

这将显示从当前终端会话运行的后台进程。你应该会看到列出的 kubectl proxy。要停止它,你可以使用 kill 命令后跟进程 ID。例如,如果 jobs 显示 [1] Running kubectl proxy --port=8080 &,则进程 ID 为 1。你将使用:

kill %1

%1 替换为 jobs 命令显示的作业 ID。或者,你可以使用 ps aux | grep kubectl proxy 找到进程 ID,然后使用 kill <PID>

关于 kubectl proxy 需要记住的关键点:

  • kubectl proxy 创建一个到 Kubernetes API 服务器的安全、已认证的连接。
  • 它允许你从当前环境访问集群资源(Pod、Service 等),就像你在集群网络内部一样。
  • 它对于调试、开发和探索 Kubernetes API 非常有用。
  • 出于安全原因,kubectl proxy 只能在 localhost (127.0.0.1) 上访问。它不适用于公开暴露服务。

总结

在这个实验中,你已成功学会了如何使用 Minikube 在 Kubernetes 集群上部署应用程序。你首先使用 Minikube 设置了 Kubernetes 集群并验证了其状态。然后,你探索了用于与集群交互和管理资源的常用 kubectl 命令。你学会了列出命名空间、获取节点和 Pod 的详细信息,并理解了 kubectl 的基本命令结构。这些步骤为你提供了与 Kubernetes 协作的坚实基础。

你接着为 Pod 和 Deployment 创建了简单的 YAML manifest,使用 kubectl apply 将它们应用到你的集群,并使用 getdescribe 等各种 kubectl 命令验证了部署状态。这种实践经验使你能够理解在 Kubernetes 上部署应用程序的声明式方法以及如何有效地与集群进行交互。

最后,你学会了如何使用 kubectl proxy 访问已部署的应用程序,它提供了一种安全的方式来与你的集群 API 交互,并从当前环境访问服务和 Pod。这是一种用于开发、调试和探索你的 Kubernetes 环境的宝贵技术。

通过完成此实验,你获得了对基本 Kubernetes 概念和工具的实践经验,为你部署和管理更复杂的 Kubernetes 应用程序奠定了基础。