启动/删除 minikube

启动minikube集群

1
minikube start

Fedora下删除minikube

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 停止运行
minikube stop;

# 执行卸载命令
minikube delete

# 移除相关配置文件
rm -r ~/.kube ~/.minikube
sudo rm /usr/local/bin/localkube /usr/local/bin/minikube

# 停止服务
systemctl stop '*kubelet*.mount'

# 删除目录
sudo rm -rf /etc/kubernetes/

访问面板

访问minikube集群中运行的k8s面板

1
minikube dashboard

启动成功,默认地址

image.png

部署、暴露及访问服务

创建一个名为hello-minikube的部署,使用的镜像是kicbase/echo-server:1.0。部署是Kubernetes中用于管理应用程序的对象,它确保指定数量的Pod(容器实例)在集群中运行,并且可以自动处理Pod的创建、更新和删除。

1
kubectl create deployment hello-minikube --image=kicbase/echo-server:1.0

控制台打印deployment.apps/hello-minikube created

将刚刚创建的hello-minikube部署暴露为一个服务,服务类型为NodePort,并将其端口设置为8080NodePort服务类型允许外部流量通过集群节点的特定端口访问服务。Kubernetes会在每个节点上分配一个端口(通常在30000-32767范围内),并将流量转发到后端的Pod

1
kubectl expose deployment hello-minikube --type=NodePort --port=8080

控制台打印service/hello-minikube exposed

在Minikube环境中访问hello-minikube服务。它会自动打开一个浏览器窗口,指向分配给该服务的NodePort地址。通过这个地址,用户可以访问到部署的应用程序

1
minikube service hello-minikube

image.png

浏览器中显示以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Request served by hello-minikube-ffcbb5874-vqdjj

HTTP/1.1 GET /

Host: 127.0.0.1:39899
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Connection: keep-alive
Sec-Ch-Ua: "Not)A;Brand";v="8", "Chromium";v="138", "Microsoft Edge";v="138"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0

新集群

minikube允许在本地运行多个集群。通过使用不同的profiles(配置文件),这些集群互相独立,并拥有不同的名称、配置和状态

本地创建名为cluster2的集群

1
minikube start -p cluster2 

列出本地所有minikube集群配置,包括状态、名称、节点等信息

1
minikube profile list

停止刚创建的cluster2集群

1
minikube stop -p cluster2

minikube指令如何不指定集群,则默认对profile minikube集群生效,比如此时有两个集群,使用stop命令,则只关闭profile minikube集群

image.png

k8s核心概念

Node

Node 是 Kubernetes 集群的最小硬件单元,可以是物理服务器或虚拟机(在 Minikube 中,节点通常是一个本地虚拟机)。所有的应用程序最终都会运行在节点上。

  • 作用
    节点是 Pod 的 “运行载体”,负责运行 Pod 中的容器,并提供计算、网络、存储等资源。

  • 组成
    每个节点会运行 Kubernetes 的核心组件(如容器运行时、kubelet、kube-proxy 等),确保 Pod 能正常启动和运行。

  • 案例关联
    在你的 Minikube 环境中,minikube start会创建一个单节点集群(这个节点就是运行所有 Pod 的虚拟机);你部署的hello-minikube相关 Pod,最终就运行在这个节点上。

Pod

Pod 是 Kubernetes 中最小的可部署单元,是容器的 “包装器”。一个 Pod 可以包含一个或多个紧密关联的容器(通常是一个主容器 + 辅助容器),这些容器共享网络(同一 Pod 内的容器可通过localhost通信)和存储资源。

  • 特点

    • Pod 是临时的(”有生命周期的”):当容器故障、节点重启或资源不足时,Pod 可能会被销毁并重新创建,其 IP 地址也会随之变化(这是 Pod 的 “动态性”)。
    • Pod 直接运行在节点上:一个节点可以运行多个 Pod,但受节点资源(CPU、内存)限制。
  • 案例关联
    你通过kubectl create deployment创建部署时,Deployment 会自动生成 Pod(由kicbase/echo-server:1.0镜像运行的容器就在这些 Pod 中)。浏览器中显示的Request served by hello-minikube-ffcbb5874-vqdjj就是具体的 Pod 名称。

Deployment

Deployment 是 Kubernetes 中的控制器,用于管理 Pod 的生命周期。它不直接运行容器,而是通过定义 “期望状态”(如需要 3 个 Pod),自动确保集群中始终有指定数量的 Pod 在运行。

  • 核心功能

    • 维持 Pod 数量:如果 Pod 因故障消失,Deployment 会自动创建新的 Pod 补充。
    • 滚动更新:当需要更新应用(如更换镜像版本)时,Deployment 会逐步替换旧 Pod(先创建新 Pod,再销毁旧 Pod),避免服务中断。
    • 回滚:如果更新后出现问题,Deployment 支持回滚到之前的稳定版本。
  • 与 Pod 的关系
    Deployment 通过 “标签选择器”(label selector)关联 Pod(给 Pod 打标签,Deployment 通过标签找到要管理的 Pod)。例如,你创建的hello-minikube部署会给它管理的 Pod 打上标签,确保只管理这些 Pod。

  • 案例关联
    kubectl create deployment hello-minikube --image=kicbase/echo-server:1.0命令定义了一个 Deployment,其 “期望状态” 是:运行 1 个基于kicbase/echo-server:1.0镜像的 Pod。Kubernetes 会自动创建并维持这个 Pod 的运行。

Service

由于 Pod 是临时的(IP 会变),直接通过 Pod 的 IP 访问应用会非常不稳定。Service 的作用是为一组 Pod 提供固定的网络访问地址,无论 Pod 如何重启或迁移,Service 的地址始终不变。

  • 核心功能

    • 负载均衡:当多个 Pod 提供同一服务时(如 Deployment 管理 3 个 Pod),Service 会将请求均匀分发到这些 Pod。
    • 固定访问点:Service 会分配一个集群内部的固定 IP(ClusterIP),并通过标签选择器关联 Pod(和 Deployment 类似,通过标签找到目标 Pod)。
  • 与 Pod 的关系
    Service 通过标签选择器绑定到一组 Pod(这些 Pod 通常由 Deployment 管理),形成 “前端 Service + 后端 Pod” 的稳定访问链路。

  • 案例关联
    kubectl expose deployment hello-minikube --type=NodePort --port=8080创建了一个 Service,它会绑定到hello-minikube部署管理的 Pod,提供 8080 端口的访问。即使 Pod 重启(IP 变化),Service 也能通过标签找到新的 Pod 并转发请求。

对外暴露

默认情况下,Service 的 ClusterIP 只能在集群内部访问(如集群内的其他 Pod)。要让外部(集群外的设备,如你的电脑)访问服务,需要通过Service 的类型实现 “对外暴露”。常见的对外暴露方式包括NodePortLoadBalancer(云环境)、Ingress等。

  • NodePort 类型

    • 原理:Kubernetes 会在集群的每个节点上开放一个端口(默认范围 30000-32767),并将这个端口的流量转发到 Service 的 ClusterIP:Port,最终到达 Pod。
    • 外部访问路径:节点IP:NodePort → Service → Pod。
  • 案例关联:你创建的NodePort类型 Service,Minikube 会在其节点(本地虚拟机)上分配一个端口(如浏览器中的127.0.0.1:39899,其中 39899 就是 NodePort),外部设备(你的电脑)通过这个端口就能访问到集群内的echo-server服务。

部署应用

使用镜像创建deployment

1
kubectl create deployment hello-minikube1 --image=kicbase/echo-server:1.0

暴露depolyment到指定端口

1
kubectl expose deployment hello-minikube1 --type=LoadBalancer --port=8080

应用从零到上线minikube

简单的演示,从零开始编写express web应用,docker打包为镜像再部署到minikube集群上

构建应用镜像

先完成一个express前后端不分离的web应用,然后为其编写dockerfile和docker-compose.yml配置文件,这里不展示具体代码,可以看这个公开仓库,里面有简单express web应用的源代码以及配置文件,可以直接git clone下来使用

构建镜像

1
docker-compose build

minikube有自己的docker环境,所以我们需要将本地镜像导入到minikube

1
minikube image load minikube-test-app:latest

在minikube集群中部署本地镜像

不同于前面用过的命令式管理,这次部署应用我们使用声明式配置管理,也就是kubectl apply指令

kubectl apply 指令的作用是将指定的配置文件里描述的资源状态应用到 Kubernetes 集群中。它会根据配置文件中的内容,在集群中创建或更新相应的资源。如果资源不存在,就创建新资源;如果资源已存在,就更新其状态以符合配置文件中的描述。该命令基于声明式配置管理理念,用户只需描述资源的期望状态,Kubernetes 会自动处理如何达到这个状态,无需像命令式管理(如create命令)那样明确告诉系统要执行什么操作。

创建用于部署test-app应用的配置文件,保存为test-app-deployment.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-app
spec:
replicas: 1
selector:
matchLabels:
app: test-app
template:
metadata:
labels:
app: test-app
spec:
containers:
- name: test-app
image: minikube-test-app:latest
imagePullPolicy: Never
ports:
- containerPort: 4040

部署应用

1
kubectl apply -f test-app-deployment.yaml

暴露应用

1
kubectl expose deployment test-app --port=4040 --target-port=4040 --type=NodePort

浏览器中访问应用,相当成功

1
minikube service test-app

image.png

image.png

补充1 - 切换minikube的docker环境

minikube docker-env输出提供了有关如何配置你的 shell 以使用 Minikube 的 Docker 守护进程的信息

1
2
3
4
5
6
7
8
minikube docker-env
# export DOCKER_TLS_VERIFY="1"
# export DOCKER_HOST="tcp://127.0.0.1:65525"
# export DOCKER_CERT_PATH="/home/kinoko/.minikube/certs"
# export MINIKUBE_ACTIVE_DOCKERD="minikube"

# # To point your shell to minikube's docker-daemon, run:
# # eval $(minikube -p minikube docker-env)

所以,我们只需要执行这句命令即可进入minikube的docker环境

1
eval $(minikube -p minikube docker-env)

退出minikube的docker环境可以使用这句

1
eval $(minikube -p minikube docker-env -u)

输出环境变量检测shell是否在minikube docker环境中

1
2
echo $DOCKER_HOST
# tcp://127.0.0.1:65525

进入minikube的docker环境后,构建应用镜像,这样的话镜像就直接构建在minikube的docker环境中,不需要手动load宿主机镜像

1
docker-compose build 

查看现有镜像,你会发现其中已经有很多k8s相关的镜像,这也证明终端确实已经切换到了minikube的docker环境

image.png

1
docker images -a
1
2
3
# REPOSITORY                                      TAG        IMAGE ID       CREATED         SIZE
# minikube-test-app latest 5ba493ef2796 4 seconds ago 169MB
# ...

补充2 - 镜像拉取策略(imagePullPolicy)

Kubernetes 的imagePullPolicy(镜像拉取策略)默认值为:

  • 若镜像标签为latest,默认策略是Always(总是尝试从远程仓库拉取,即使本地有镜像)。
  • 若镜像标签为非latest(如v1),默认策略是IfNotPresent(本地有则使用本地,否则拉取远程)。

也就是说,如果你在minikube docker中构建了镜像,但是在create时直接指定本地镜像名称

1
2
3
# 以下两条命令效果一致,不指定标签也是默认:latest
kubectl create deployment test-app --image=minikube-test-app:latest
kubectl create deployment test-app --image=minikube-test-app

这也会导致部署服务失败,因为此时monikube会遵循镜像拉取策略拉取远程镜像,而远程镜像仓库显然没有我们的镜像,所以会部署服务失败。

所以最好还是使用声明式配置管理,也就是创建.yaml文件并使用apply指令。

kubectl常用命令

查看资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 查看 Node
kubectl get nodes
kubectl describe node <node-name>

# 查看 Deployment
kubectl get deployments
kubectl get deployments -o wide # 显示详细信息
kubectl describe deployment <deployment-name>

# 查看 Pod
kubectl get pods
kubectl get pods -o wide
kubectl describe pod <pod-name>
kubectl get pods -n <namespace> # 指定命名空间

# 查看 Service
kubectl get services
kubectl describe service <service-name>

创建/增加资源

1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建 Deployment(基于 YAML 文件)
kubectl apply -f deployment.yaml

# 直接创建 Deployment(命令行)
kubectl create deployment <deployment-name> --image=<image-name>
kubectl scale deployment <deployment-name> --replicas=3 # 设置副本数

# 创建 Service(基于 YAML 文件)
kubectl apply -f service.yaml

# 创建 Node(通常通过 kubeadm 等工具完成,而非直接用 kubectl)
# 1. 在新节点执行加入命令
kubeadm join <control-plane-host>:<port> --token <token> --discovery-token-ca-cert-hash <hash>

删除资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 删除 Node(需先驱逐 Pod)
kubectl drain <node-name> --ignore-daemonsets
kubectl delete node <node-name>

# 删除 Deployment
kubectl delete deployment <deployment-name>
kubectl delete -f deployment.yaml # 基于 YAML 文件删除

# 删除 Pod
kubectl delete pod <pod-name>

# 删除 Service
kubectl delete service <service-name>
kubectl delete -f service.yaml

其他管理操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 更新 Deployment(滚动更新)
kubectl set image deployment/<deployment-name> <container-name>=<new-image>
kubectl rollout status deployment/<deployment-name>
kubectl rollout history deployment/<deployment-name>
kubectl rollout undo deployment/<deployment-name> # 回滚

# 重启 Pod
kubectl rollout restart deployment/<deployment-name>

# 查看 Pod 日志
kubectl logs <pod-name>
kubectl logs -f <pod-name> # 实时跟踪日志

# 进入 Pod 内部
kubectl exec -it <pod-name> -- /bin/sh

# 端口转发(访问集群内服务)
kubectl port-forward service/<service-name> 8080:80

# 标签管理
kubectl label nodes <node-name> <label-key>=<label-value>
kubectl label pods <pod-name> <label-key>=<label-value> --overwrite

常用选项

1
2
3
4
5
6
-n <namespace>        # 指定命名空间
-o wide # 显示详细信息
-o yaml # 输出 YAML 格式
--watch # 实时监控资源变化
--dry-run=client # 预览操作,不实际执行
--all-namespaces # 所有命名空间