介绍
在本实验中,你将学习如何使用多种技术暴露 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
这些命令确认了以下内容:
- Minikube 已成功运行
- 本地 Kubernetes 集群已创建
- 集群已准备就绪
- 你拥有一个具有控制平面功能的单节点集群
部署示例应用程序
在这一步中,你将学习如何使用 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:帮助部署管理正确的 Podtemplate:定义 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 由两个组件组成:
- Ingress 资源:定义路由规则的 Kubernetes API 对象
- 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 示例。


