部署一个简单的应用
实验目标:
部署一个简单的 web 应用,比如 Nginx 或者一个自定义的 Node.js 应用。
实验步骤:
- 创建一个 Deployment。
- 创建一个 Service 来暴露应用。
- 验证应用是否可以通过 Service 访问。
今天我们来做一下昨天分享的可练习实验中的第一个实验:部署一个Nginx程序
1、创建命名空间
kubectl create namespace nginx
2、在指定命名空间中创建资源
kubectl create deployment nginx -n nginx --image nginx:alpine --replicas=3# -n 指定namespaces
# --images 指定镜像
# --replicas 指定副本数量
此处需要注意,一般查询都是从默认的 default 空间中去寻找,但是我们在创建命令中指定了名称空间,在查询的时候要注意带上相对应的名称空间
跑起来的容器会自动分配一个IP地址来供访问
kubectl get pods -n nginx -o wide
在3个node节点上都有分配,负载很平均
3、 创建Service 来暴露应用
此时在容器内为互通状态,容器外仍为隔离
kubectl create service nodeport nginx --tcp=80:80 -n nginx# 一定要指定名称空间,这样才会和你的 Deployment 位于同一个命名空间
# NodePort 是一种 Service 类型,允许你通过集群节点上的特定端口从外部访问服务。
# nodeport的名称可以不与创建的pod或者deployment的名称一致
使用命令查看具体的外部地址
kubectl get service nginx -n nginx
尝试从外部访问 NGINX 服务,使用集群节点的 IP 地址和 NodePort 端口:
验证从外部可以访问:
在 Kubernetes 中,当你从集群外部访问一个 NodePort 类型的 Service 时,请求会被随机分配到与该 Service 关联的任意一个 Pod。这是因为 Kubernetes Service 使用负载均衡机制来将流量分配到所有匹配的 Pods 上,从而实现高可用性和负载均衡。
负载均衡和流量分配: Kubernetes Service 使用 轮询
或 随机
的负载均衡算法将流量分配到所有匹配的 Pods 上。这个过程对用户是透明的,你无法指定请求访问特定的 Pod。
验证请求分配: 如果你想验证请求被分配到哪个 Pod,可以在每个 Pod 的 NGINX 配置中输出一些标识信息,或者在每个 Pod 中运行一个简单的 HTTP 服务来返回 Pod 的名字。
进入每个 Pod 并创建一个标识文件:
kubectl exec -it <pod-name> -n nginx -- sh -c "echo $(hostname) > /usr/share/nginx/html/index.html"#替换 <pod-name> 为每个 Pod 的实际名称。
# 请在不同的node节点上分别执行,否则hostname的名称可能会重复,看不到实际效果
每次刷新或再次访问 URL,你应该会看到不同的 Pod 名称,这表明请求正在负载均衡到不同的 Pods。
问题总结
虽然看起来部署一个应用比较简单,但也有可能出错的地方。
常见问题: 外部访问时无法连接到 Kubernetes NodePort 服务该怎么办呢
1、检查pod状态
kubectl get pods -n nginx
确保所有 Pods 都显示为 Running 状态。如果有 Pods 处于 Pending 或 Error 状态,进一步查看日志和事件:
kubectl describe pod <pod-name> -n nginx
kubectl logs <pod-name> -n nginx
2、检查service的选择器
确保 Service 的选择器正确匹配到正在运行的 Pods。查看 Service 的详细信息:
kubectl get service nginx -n nginx -o yaml
应该可以看到类似以下的输出:
apiVersion: v1
kind: Service
metadata:creationTimestamp: "2024-06-15T07:15:03Z"labels:app: nginxname: nginxnamespace: nginxresourceVersion: "116170"uid: 57f1e070-5a8f-4c77-9a92-e7d8072d987c
spec:clusterIP: 10.104.10.231clusterIPs:- 10.104.10.231externalTrafficPolicy: ClusterinternalTrafficPolicy: ClusteripFamilies:- IPv4ipFamilyPolicy: SingleStackports:- name: 80-80nodePort: 31151port: 80protocol: TCPtargetPort: 80selector:app: nginx #这里请注意是否正确匹配到pods的标签sessionAffinity: Nonetype: NodePort
status:loadBalancer: {}
确保 selector 部分正确匹配到 Pods 的标签。查看 Pods 的标签:
kubectl get pods -n nginx --show-labels
3、检查Endopints
查看 Service 的 Endpoints 确认是否有可用端点:
kubectl get endpoints nginx -n nginx
4、检查pod监听的端口
确认 Pods 中的 NGINX 容器是否在监听端口 80。进入一个 Pod 并检查:
5、检查nodeport端口设置
确保节点防火墙允许 NodePort 端口通过(默认范围是 30000-32767)
kubectl get service nginx -n nginx
如果发现防火墙上有相关的报错信息。比如这种情况:
REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 /* nginx/nginx-service:80-80 has no endpoints */ ADDRTYPE match dst-type LOCAL tcp dpt:31634 reject-with icmp-port-unreachable
这个错误信息表明,Service nginx/nginx-service 的端口 80 没有可用的端点(Pods)。这可能是因为相关 Pods 没有运行或者标签选择器没有正确匹配到这些 Pods。这个时候都要回头去检查第2步是否有误。
删除(可选)
只是作为扩展知识,后续实验可能仍会用到。也可删除试一下能否彻底清除
要停止并删除创建的三个nginx容器。可以使用 kubectl delete pod
命令。首先,你需要知道这两个 Pods 所在的命名空间。当然了我们自己创建的pods我们肯定是清楚的。如果是已经在运行中的且无法判断是否在 default
命名空间中,可以参考以下步骤
1、查看pods所在命名空间
kubectl get pods --all-namespaces
2、删除pods
kubectl delete pod nginx-b4ccb96c6-lhb4l -n nginx
3、验证删除
删除操作完成后,可以再次检查以确认 Pods 已被删除:
kubectl get pods -n nginx
这将完全停止并删除指定的 Pods。如果你使用的是 Deployment
、ReplicaSet
或其他控制器来管理这些 Pods,它们可能会自动重新创建这些 Pods。在这种情况下,你可能需要删除或更新相应的控制器资源。
这里我删了两个容器后,Deployment 马上就又创建了两个新的pods容器。因为我们在最初的创建命令中添加了 --replicas=3
参数。保证它永远会存在3个副本。那这种情况该如何删除呢?
删除 Deployment 资源
1、查找Deployment
首先,确认 Pods 是由哪个 Deployment 管理的。你可以查看所有 Deployments:
kubectl get deployments --all-namespaces
2、删除 Deployment
一旦你确定了管理这些 Pods 的 Deployment 名称,可以删除该 Deployment:
kubectl delete deployment <deployment-name> -n nginx
如果你不想完全删除 Deployment,只是想修改其配置(例如,减少副本数量)
可以更新 Deployment:
1、更新副本数量:
例如,将副本数量缩减为0
kubectl scale deployment <deployment-name> --replicas=0 -n nginx
2、如果你有一个新的Deployment 配置文件,可以应用新的配置:
kubectl apply -f <path-to-new-deployment-file>
删除 ReplicaSet 或其他控制器资源
如果 Pods 是由 ReplicaSet 或其他控制器(如 StatefulSet、DaemonSet)管理的,可以使用类似的方法:
1、查找控制器资源:
kubectl get replicasets -n default
或者:
kubectl get statefulsets -n default
kubectl get daemonsets -n default
2、删除控制器资源:
kubectl delete replicaset <replicaset-name> -n default
kubectl delete statefulset <statefulset-name> -n default
kubectl delete daemonset <daemonset-name> -n default
注意:
当你删除一个 Deployment 时,Kubernetes 会自动删除由该 Deployment 创建和管理的所有 Pods 和 ReplicaSet。