暴露 Kubernetes 应用程序

KubernetesBeginner
立即练习

介绍

在本实验中,你将学习如何使用多种技术暴露 Kubernetes 应用程序,包括创建内部和外部服务、使用标签以及探索 Ingress 的基础知识。你将首先使用 Minikube 设置一个本地 Kubernetes 集群,然后部署一个示例 NGINX 应用程序,并将其在内部和外部暴露。你还将探索如何使用标签来组织和选择资源,最后,你将了解 Ingress 并查看一个简单的 Ingress YAML 示例。

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

启动 Kubernetes 集群

在这一步中,你将学习如何使用 Minikube 启动并验证一个本地 Kubernetes 集群。这是在本地机器上开发和测试 Kubernetes 应用程序的重要第一步。

首先,启动 Minikube 集群:

minikube start

示例输出:

😄  minikube v1.29.0 on Ubuntu 22.04
✨  自动选择 docker 驱动
📌  使用 Docker 驱动并具有 root 权限
🔥  在 Kubernetes 集群中创建 Kubernetes
🔄  重启现有的 Kubernetes 集群
🐳  在 Docker 20.10.23 上准备 Kubernetes v1.26.1 ...
🚀  启动 Kubernetes ...
🌟  启用插件:storage-provisioner, default-storageclass
🏄  完成!kubectl 现在已配置为使用 "minikube" 集群和 "default" 命名空间

使用多个命令验证集群状态:

minikube status
kubectl get nodes

minikube status 的示例输出:

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

kubectl get nodes 的示例输出:

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

这些命令确认了以下内容:

  1. Minikube 已成功运行
  2. 本地 Kubernetes 集群已创建
  3. 集群已准备就绪
  4. 你拥有一个具有控制平面功能的单节点集群

部署示例应用程序

在这一步中,你将学习如何使用 YAML 清单文件创建并部署一个 Kubernetes 应用程序。我们将创建一个简单的 NGINX Web 服务器部署,以演示定义和应用 Kubernetes 资源的过程。

首先,为你的 Kubernetes 清单文件创建一个目录:

mkdir -p ~/project/k8s-manifests
cd ~/project/k8s-manifests

创建一个用于 NGINX 部署的 YAML 文件:

nano 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

保存文件(按 Ctrl+X,然后按 Y,最后按 Enter)。

将部署应用到 Kubernetes 集群:

kubectl apply -f nginx-deployment.yaml

示例输出:

deployment.apps/nginx-deployment created

验证部署和 Pod:

kubectl get deployments
kubectl get pods

kubectl get deployments 的示例输出:

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

kubectl get pods 的示例输出:

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

等待 Pod 进入 "Running" 状态后再继续。

让我们分解一下 YAML 清单:

  • apiVersion:指定 Kubernetes API 版本
  • kind:定义资源类型(Deployment)
  • metadata:为部署提供名称和标签
  • spec.replicas:设置 Pod 副本的数量
  • selector:帮助部署管理正确的 Pod
  • template:定义 Pod 的规格
  • containers:指定容器镜像和端口

此部署创建了三个相同的 NGINX Pod,展示了 Kubernetes 如何管理容器化应用程序。

通过 YAML 创建服务以内部或外部暴露应用程序

在这一步中,你将学习如何创建 Kubernetes 服务以内部和外部暴露你的 NGINX 部署。我们将演示两种常见的服务类型:ClusterIP 和 NodePort。

首先,导航到你的项目目录:

cd ~/project/k8s-manifests

创建一个 ClusterIP 服务的 YAML 文件:

nano nginx-clusterip-service.yaml

添加以下服务清单内容:

apiVersion: v1
kind: Service
metadata:
  name: nginx-clusterip-service
spec:
  selector:
    app: nginx
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 80

现在,创建一个 NodePort 服务的 YAML 文件:

nano nginx-nodeport-service.yaml

添加以下服务清单内容:

apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport-service
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080

应用这两个服务配置:

kubectl apply -f nginx-clusterip-service.yaml
kubectl apply -f nginx-nodeport-service.yaml

示例输出:

service/nginx-clusterip-service created
service/nginx-nodeport-service created

验证服务:

kubectl get services

示例输出:

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes                  ClusterIP   10.96.0.1        <none>        443/TCP        30m
nginx-clusterip-service     ClusterIP   10.104.xxx.xxx   <none>        80/TCP         1m
nginx-nodeport-service      NodePort    10.108.yyy.yyy   <none>        80:30080/TCP   1m

要访问 NodePort 服务,获取 Minikube 的 IP 地址:

minikube ip

示例输出:

192.168.49.2

服务类型的关键区别:

  • ClusterIP:仅限集群内部访问
  • NodePort:在每个节点的 IP 上通过静态端口暴露服务
  • NodePort 范围:30000-32767

验证服务配置

在这一步中,你将学习如何使用 kubectl describe service 来检查 Kubernetes 服务的详细配置,并了解其网络属性。

首先,确保你在项目目录中:

cd ~/project/k8s-manifests

详细描述 ClusterIP 服务:

kubectl describe service nginx-clusterip-service

示例输出:

Name:              nginx-clusterip-service
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.104.xxx.xxx
IPs:               10.104.xxx.xxx
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.0.7:80,10.244.0.8:80,10.244.0.9:80
Session Affinity:  None
Events:            <none>

现在,描述 NodePort 服务:

kubectl describe service nginx-nodeport-service

示例输出:

Name:                     nginx-nodeport-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.108.yyy.yyy
IPs:                      10.108.yyy.yyy
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30080/TCP
Endpoints:                10.244.0.7:80,10.244.0.8:80,10.244.0.9:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

检查服务端点以验证网络连接性:

kubectl get endpoints

示例输出:

NAME                        ENDPOINTS                               AGE
kubernetes                  192.168.49.2:8443                       45m
nginx-clusterip-service     10.244.0.7:80,10.244.0.8:80,10.244.0.9:80   15m
nginx-nodeport-service      10.244.0.7:80,10.244.0.8:80,10.244.0.9:80   15m

从服务描述中需要理解的关键信息:

  • Selector:显示哪些 Pod 属于该服务
  • IP:服务的集群内部 IP 地址
  • Endpoints:提供服务 Pod 的 IP 地址和端口列表
  • Port 和 TargetPort:定义流量如何路由
  • NodePort:NodePort 服务类型的外部端口

使用标签组织和选择资源

在这一步中,你将学习如何在 Kubernetes 中使用标签来高效地组织和选择资源。标签是键值对,可以帮助你管理和组织 Kubernetes 对象。

首先,验证当前 Pod 上的标签:

kubectl get pods --show-labels

示例输出:

NAME                                READY   STATUS    RESTARTS   AGE   LABELS
nginx-deployment-xxx-yyy            1/1     Running   0          30m   app=nginx,pod-template-hash=xxx
nginx-deployment-xxx-zzz            1/1     Running   0          30m   app=nginx,pod-template-hash=yyy
nginx-deployment-xxx-www            1/1     Running   0          30m   app=nginx,pod-template-hash=zzz

使用特定标签选择 Pod:

kubectl get pods -l app=nginx

示例输出:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-xxx-yyy            1/1     Running   0          30m
nginx-deployment-xxx-zzz            1/1     Running   0          30m
nginx-deployment-xxx-www            1/1     Running   0          30m

让我们为其中一个 Pod 添加一个自定义标签:

kubectl label pods nginx-deployment-xxx-yyy environment=development

nginx-deployment-xxx-yyy 替换为你其中一个 Pod 的名称。

示例输出:

pod/nginx-deployment-xxx-yyy labeled

现在,使用多个标签选择器选择 Pod:

kubectl get pods -l app=nginx,environment=development

示例输出:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-xxx-yyy            1/1     Running   0          30m

从 Pod 中移除一个标签:

kubectl label pods nginx-deployment-xxx-yyy environment-

示例输出:

pod/nginx-deployment-xxx-yyy unlabeled

在服务中演示标签选择:

kubectl describe service nginx-clusterip-service

查看 "Selector" 部分,它展示了服务如何使用标签来识别 Pod。

关于标签的关键点:

  • 标签是附加到 Kubernetes 对象上的键值对
  • 用于组织、选择和过滤资源
  • 可以动态添加、修改或移除
  • 服务和部署使用标签来管理相关的 Pod

删除和管理服务

在这一步中,你将学习如何使用 kubectl 命令删除和管理 Kubernetes 服务。了解服务管理对于维护和清理你的 Kubernetes 资源至关重要。

首先,列出当前的服务:

kubectl get services

示例输出:

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes                  ClusterIP   10.96.0.1        <none>        443/TCP        1h
nginx-clusterip-service     ClusterIP   10.104.xxx.xxx   <none>        80/TCP         45m
nginx-nodeport-service      NodePort    10.108.yyy.yyy   <none>        80:30080/TCP   45m

使用 kubectl delete 删除特定的服务:

kubectl delete service nginx-clusterip-service

示例输出:

service "nginx-clusterip-service" deleted

验证服务是否已删除:

kubectl get services

示例输出:

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes                  ClusterIP   10.96.0.1        <none>        443/TCP        1h
nginx-nodeport-service      NodePort    10.108.yyy.yyy   <none>        80:30080/TCP   45m

为了更清楚地演示多个服务的删除,让我们重新创建服务,然后一起删除它们:

## Recreate services
kubectl apply -f nginx-clusterip-service.yaml
kubectl apply -f nginx-nodeport-service.yaml
## Delete multiple services at once
kubectl delete service nginx-clusterip-service nginx-nodeport-service

示例输出:

service "nginx-clusterip-service" deleted
service "nginx-nodeport-service" deleted

验证所有服务是否已被移除(除了默认的 kubernetes 服务):

kubectl get services

示例输出:

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

关于服务删除的关键点:

  • 删除服务会移除网络端点
  • 删除服务时,Pod 不会被删除
  • 默认的 kubernetes 服务不能被删除
  • 你可以使用名称、YAML 文件或标签来删除服务
  • 可以通过列出服务名称或使用标签选择器同时删除多个服务

介绍 Ingress 基础并展示一个简单的 Ingress YAML 示例

在这一步中,你将了解 Kubernetes Ingress,它是管理对 Kubernetes 集群中服务的外部访问的强大方式。

什么是 Ingress?

Ingress 是一个 API 对象,用于管理对 Kubernetes 集群中服务的外部访问,通常是 HTTP 访问。Ingress 提供以下功能:

  • 负载均衡:将流量分发到多个后端服务
  • SSL/TLS 终止:处理安全连接
  • 基于名称的虚拟主机:根据主机名将请求路由到不同的服务
  • 基于路径的路由:根据 URL 路径将请求路由到不同的服务

Ingress 由两个组件组成:

  1. Ingress 资源:定义路由规则的 Kubernetes API 对象
  2. Ingress 控制器:强制执行 Ingress 资源中定义的规则的实现

注意:本实验仅对 Ingress 进行了基本介绍。在生产环境中,Ingress 配置可能会复杂得多,包括高级路由、身份验证、速率限制等。

让我们在 Minikube 中启用 Ingress 插件:

minikube addons enable ingress

示例输出:

💡  ingress 是由 Kubernetes 维护的插件。如有任何问题,请在 GitHub 上联系 Minikube。
🔉  ingress 已成功启用

为两个示例应用程序创建部署:

kubectl create deployment web1 --image=nginx:alpine
kubectl create deployment web2 --image=httpd:alpine

将这些部署作为服务暴露:

kubectl expose deployment web1 --port=80 --type=ClusterIP --name=web1-service
kubectl expose deployment web2 --port=80 --type=ClusterIP --name=web2-service

创建一个 Ingress YAML 文件:

nano ingress-example.yaml

添加以下 Ingress 配置:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - http:
        paths:
          - path: /web1
            pathType: Prefix
            backend:
              service:
                name: web1-service
                port:
                  number: 80
          - path: /web2
            pathType: Prefix
            backend:
              service:
                name: web2-service
                port:
                  number: 80

此 Ingress 配置的关键组件:

  • metadata.annotations:Ingress 控制器的特定配置
  • spec.rules:定义如何将流量路由到服务
  • path:将匹配的 URL 路径
  • pathType:路径应如何匹配(Prefix、Exact 或 ImplementationSpecific)
  • backend.service:要将流量路由到的服务和端口

应用 Ingress 配置:

kubectl apply -f ingress-example.yaml

验证 Ingress 资源:

kubectl get ingress

示例输出:

NAME              CLASS   HOSTS   ADDRESS        PORTS   AGE
example-ingress   nginx   *       192.168.49.2   80      1m

查看 Ingress 详细信息:

kubectl describe ingress example-ingress

示例输出将显示路由规则和后端服务。

测试 Ingress:

## 获取 Minikube IP
minikube ip

## 测试通过 Ingress 访问服务
curl $(minikube ip)/web1
curl $(minikube ip)/web2

每个命令应返回相应 Web 服务器的默认页面。

在生产环境中,Ingress 可以配置以下内容:

  • 多个基于主机名的规则
  • 用于 HTTPS 的 TLS 证书
  • 身份验证机制
  • 速率限制
  • 自定义超时配置
  • 会话亲和性
  • 以及更多高级功能

要更全面地了解 Ingress,请参考 Kubernetes 文档,并考虑探索专门的 Ingress 控制器文档,如 NGINX Ingress 或 Traefik。

总结

在本实验中,你学习了如何使用 Minikube 启动并验证一个本地 Kubernetes 集群,这是在本地机器上开发和测试 Kubernetes 应用程序的重要第一步。随后,你使用 YAML 清单文件创建并部署了一个简单的 NGINX Web 服务器部署,演示了定义和应用 Kubernetes 资源的过程。此外,你还学习了如何创建 Kubernetes 服务以内部或外部暴露你的应用程序,以及如何使用标签来组织和选择资源。最后,你探索了 Kubernetes Ingress 的基础知识,并查看了一个简单的 Ingress YAML 示例。