暴露 Kubernetes 应用程序

KubernetesBeginner
立即练习

介绍

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

启动 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 示例。