使用minikube搭建k8s集群:
安装kubectl
https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/
$ curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 138 100 138 0 0 151 0 --:--:-- --:--:-- --:--:-- 151
100 53.7M 100 53.7M 0 0 16190 0 0:58:02 0:58:02 --:--:-- 13459
赋予执行权限:
$ chmod +x ./kubectl
然后:
$ sudo mv ./kubectl /usr/local/bin/
上面两步也可以直接: sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
解释这个命令:
sudo install: install 命令用于复制文件并设置目标文件的权限和所有者。在这里我们使用 sudo 来以超级用户身份执行这个操作,确保有足够权限将文件安装到 /usr/local/bin。
-o root:指定目标文件的所有者为 root 用户。即 kubectl 文件将归 root 用户所有。
-g root:指定目标文件的用户组为 root。即文件将属于 root 用户组。
-m 0755:设置目标文件的权限为 0755,即文件所有者(root)具有读、写、执行权限,其他用户和用户组具有读、执行权限。这是常见的可执行文件权限设置。
kubectl:这是源文件的路径,即你之前下载的 kubectl 二进制文件。
/usr/local/bin/kubectl:这是目标文件路径,kubectl 将被安装到 /usr/local/bin/ 目录下,这样它就可以全局访问。
#####kubectl常规命令
删除集群
kind delete cluster --name kind 或者 kind delete clusters --all
查看集群的节点:
kubectl get nodes
查看所有 Pod:
kubectl get pods --all-namespaces
查看运行中的部署:
kubectl get deployments
查看日志:
kubectl describe pod -n kube-flannel <POD_NAME>
删除资源
kubectl delete -f kube-flannel.yml
重新运行
kubectl apply -f kube-flannel.yml
#####配置docker cli代理
vim ~/.docker/config.json
{
"proxies": {
"default": {
"httpProxy": "http://127.0.0.1:7890",
"httpsProxy": "http://127.0.0.1:7890",
"noProxy": "localhost,127.0.0.1"
}
}
}
这样可以直接docker pull 等操作
最后直接去 docker hub 找到镜像: https://hub.docker.com/r/flannel/flannel-cni-plugin/tags
然后通过 cli 拉取: docker pull flannel/flannel-cni-plugin:v1.6.0-flannel1
#####使用minikube搭建k8s集群
前提需要kubectl安装完毕
1.minikube 安装
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
2.启动
minikube start
这个命令会创建并启动一个本地的Kubernetes集群。默认情况下,Minikube会使用Docker驱动。默认: minikube start --driver=docker, 可以换其它驱动,如: minikube start --driver=virtualbox。分配资源: minikube start --cpus 4 --memory 8192
注意: Minikube 是一个本地的 Kubernetes 集群管理工具,它可以使用容器(如 Docker)或者虚拟机技术来运行。当你使用 Docker 驱动时,Minikube 本质上是通过在 Docker 容器内运行 Kubernetes 控制平面和工作负载来模拟一个 Kubernetes 集群。所以一定要注意一个问题,宿主机上的docker和通过Minikube创建的容器中的docker是不一样的,前面所有的代理问题都和这个有关系,比如后面想搭建一个redis集群,yaml文件的镜像拉取失败,最后的解决办法是在宿主机上执行: docker pull redis:6.2 (我配置了docker cli 代理,左翼是可以拉取镜像),然后将镜像加载到 Minikube,通过: minikube image load redis:6.2,最后才可以运行起来.
关于minikube代理配置,参考: https://minikube.sigs.k8s.io/docs/handbook/vpn_and_proxy/
3.查看集群状态
# 查看集群信息
kubectl cluster-info
正常情况如下提示:
Kubernetes control plane is running at https://192.168.49.2:8443
CoreDNS is running at https://192.168.49.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
# 查看节点状态
kubectl get nodes
正常情况如下提示:
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 6m14s v1.31.0
4.停止集群
minikube stop
5.删除集群
minikube delete
6.查看集群仪表板
minikube dashboard
这将启动 Dashboard,并自动在浏览器中打开一个界面。你不需要手动启动 kubectl proxy,Minikube 会为你处理这一切。与 kubectl 命令一样,Dashboard 也需要适当的权限。如果你正在使用 Minikube,它会使用 Minikube 默认的配置和权限,通常你无需做额外的设置。
7.ssh进入Minikube虚拟机
minikube ssh
#####使用minikube搭建的k8s,搭建 redis 集群
分别准备两个yaml文件
guoshipeng@k8s:/usr/local/k8s-local/redis-cluser$ kubectl apply -f redis-service.yaml
service/redis-service created
guoshipeng@k8s:/usr/local/k8s-local/redis-cluser$ kubectl apply -f redis-statefulset.yaml
statefulset.apps/redis created
guoshipeng@k8s:/usr/local/k8s-local/redis-cluser$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 130m v1.31.0
guoshipeng@k8s:/usr/local/k8s-local/redis-cluser$
guoshipeng@k8s:/usr/local/k8s-local/redis-cluser$ kubectl get pods
NAME READY STATUS RESTARTS AGE
redis-0 1/1 Running 0 15s
redis-1 1/1 Running 0 11s
redis-2 1/1 Running 0 8s
//宿主机直接连接
$ redis-cli -h 192.168.49.2 -p 30079
// 直接 set key 发现报错,突然想起来,我这是一个k8s的redis集群,需要为集群内的节点分配slot
CLUSTERDOWN Hash slot not served
192.168.49.2:30079> cluster nodes
f8c27f635bee637fa579274b11cac1834078eb27 :6379@16379 myself,master - 0 0 0 connected
192.168.49.2:30079> cluster info
cluster_state:fail
cluster_slots_assigned:0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:1
cluster_size:0
cluster_current_epoch:0
cluster_my_epoch:0
cluster_stats_messages_sent:0
cluster_stats_messages_received:0
说明集群有问题,没有互通
// 默认k8s集群内的三个节点的互通ip为 10.0.0.1:6379 10.0.0.2:6379 10.0.0.3:6379,如果是在某个worker上执行如下命令,那么只需要meet其它两个就可以了,不再要meet自己,但是我们这里是通过k8s搭建的redis集群,所以需要分别meet这三个
192.168.49.2:30079> cluster meet 10.0.0.1 6379
OK
192.168.49.2:30079> cluster meet 10.0.0.2 6379
OK
192.168.49.2:30079> cluster meet 10.0.0.3 6379
OK
再次设置key,但是还是报(可能出现):
CLUSTERDOWN Hash slot not served
这个问题说明集群存在hash槽异常情况,那么,可以执行以下指令修复下手动修复slot分配问题:
$ redis-cli --cluster fix 192.168.49.2:30079
192.168.49.2:30079 (3f92737a...) -> 0 keys | 0 slots | 0 slaves.
[OK] 0 keys in 1 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 192.168.49.2:30079)
M: 3f92737a49748ebde447c7c5cba49ce01bc241e9 192.168.49.2:30079
slots: (0 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[ERR] Not all 16384 slots are covered by nodes.
>>> Fixing slots coverage...
The following uncovered slots have no keys across the cluster:
[0-16383]
Fix these slots by covering with a random node? (type 'yes' to accept): yes
...
...
>>> Covering slot 16282 with 192.168.49.2:30079
>>> Covering slot 1501 with 192.168.49.2:30079
>>> Covering slot 3300 with 192.168.49.2:30079
>>> Covering slot 14876 with 192.168.49.2:30079
>>> Covering slot 13993 with 192.168.49.2:30079
>>> Covering slot 10272 with 192.168.49.2:30079
>>> Covering slot 694 with 192.168.49.2:30079
...
...
再次:
$ redis-cli -h 192.168.49.2 -p 30079
192.168.49.2:30079> cluster nodes
cfdfa8b787ea1fe5bcbb15fb6bf548113a1a5939 10.0.0.2:6379@16379 handshake - 0 0 0 connected
41059609d6a7a9a76642788bac228a08fc1dd01f :6379@16379 myself,master - 0 0 1 connected 0-16383 // 但是不确定这个来自哪里
5c2813c1186543cea74d51a77b5d620b367d65a9 10.0.0.3:6379@16379 handshake - 0 0 0 connected
af2ea4819716fc39def29441bd1bef4cd6142151 10.0.0.1:6379@16379 handshake - 0 0 0 connected
192.168.49.2:30079> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:3
cluster_size:1
cluster_current_epoch:1
cluster_my_epoch:1
cluster_stats_messages_sent:0
cluster_stats_messages_received:0
现在信息正常了
然后设置key信息
但是后来再执行:
192.168.49.2:30079> cluster nodes
41059609d6a7a9a76642788bac228a08fc1dd01f :6379@16379 myself,master - 0 0 1 connected 0-16383
只有上面一条
192.168.49.2:30079> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:1
cluster_size:1
cluster_current_epoch:1
cluster_my_epoch:1
cluster_stats_messages_sent:0
cluster_stats_messages_received:0
还是正常的
我发现退出当前连接:
192.168.49.2:30079> exit
再次进来:
$ redis-cli -h 192.168.49.2 -p 30079
192.168.49.2:30079> cluster info
cluster_state:fail
cluster_slots_assigned:0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:1
cluster_size:0
cluster_current_epoch:0
cluster_my_epoch:0
cluster_stats_messages_sent:0
cluster_stats_messages_received:0
192.168.49.2:30079>
192.168.49.2:30079> cluster nodes
f8c27f635bee637fa579274b11cac1834078eb27 :6379@16379 myself,master - 0 0 0 connected
发现redis集群又不能访问了,主要是集群hash又有问题了,需要重新redis-cli --cluster fix 192.168.49.2:30079,反正有问题要么重新hash,要么meet节点
删除redis集群:
$ kubectl delete -f redis-service.yaml
service "redis-service" deleted
$ kubectl delete -f redis-statefulset.yaml
statefulset.apps "redis" deleted
redis-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-service
labels:
app: redis
spec:
type: NodePort
ports:
- port: 6379 # Redis 服务的端口
targetPort: 6379 # Pod 中 Redis 容器的端口
nodePort: 30079 # 暴露到主机的端口
selector:
app: redis
redis-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: "redis-service"
replicas: 3
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:6.2
ports:
- containerPort: 6379
volumeMounts:
- name: data
mountPath: /data
args:
- "redis-server"
- "--appendonly"
- "yes"
- "--cluster-enabled"
- "yes"
- "--cluster-config-file"
- "/data/nodes.conf"
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
#####StatefulSet的作用
StatefulSet 是 Kubernetes 中的一种控制器,专门设计用于管理 有状态应用 的部署和扩展。它提供了一种机制来确保应用实例的标识、存储和顺序在扩展或重启时保持一致。
StatefulSet 的特点
1.稳定的网络标识(Stable Network Identity) 每个 Pod 都有一个唯一的名称,以 StatefulSet 名称 + 索引号 的形式命名,例如 redis-0, redis-1, redis-2。
这些 Pod 会通过一个 Headless Service 暴露,并拥有稳定的 DNS 名称(如 redis-0.redis-headless.default.svc.cluster.local),即使 Pod 被删除重建,其 DNS 名称也保持不变。
2.稳定的存储(Stable Storage) 每个 Pod 都可以使用一个独立的 PersistentVolume,这些卷与 Pod 紧密绑定。即使 Pod 被删除,卷中的数据仍然保留,并在 Pod 重建时重新挂载。
3.有序部署和更新(Ordered, Graceful Deployment and Scaling) Pods 的创建、更新和删除按顺序进行。例如:
按索引从小到大逐个创建 Pod。
更新时,会等待前一个 Pod 更新完成并处于 Ready 状态后再更新下一个。
删除 Pods 时,会按索引从大到小逐步删除。
4.支持有状态工作负载 StatefulSet 是为那些需要对每个实例保持唯一状态的工作负载设计的,比如数据库(Redis、MySQL、Cassandra 等)、分布式缓存、消息队列等。
#####StatefulSet 的使用场景
1.分布式数据库 如 Redis 集群、Cassandra、MongoDB 等,它们需要稳定的网络标识和持久化存储。
2.分布式文件系统 如 HDFS、Ceph、GlusterFS。
3.需要顺序依赖的服务 一些服务需要按照特定顺序启动,比如主节点需要先启动,随后是从节点。
4.任何有状态的应用 比如 Kafka、Zookeeper、Elasticsearch。
#####StatefulSet 的行为
扩容:添加一个新 Pod(如 redis-3),并分配新的存储卷。
缩容:删除一个 Pod(如 redis-2),但卷不会自动删除。
重启:重新创建时,Pod 和存储的关系保持一致。
#####StatefulSet vs Deployment
特性 StatefulSet Deployment
Pod的命名 稳定(如 redis-0, redis-1) 动态生成(如 nginx-xyzabc)
存储 持久化,每个 Pod 独立存储 通常为临时存储
网络标识 固定的 DNS 名称 动态分配的 IP 和主机名
应用场景 数据库、分布式系统、缓存等有状态服务 无状态服务,如 Web 应用
更新顺序 按序更新(0 -> N) 无特定顺序
总结:
StatefulSet 是 Kubernetes 中管理有状态应用的核心组件,提供了稳定的标识和存储,适合需要持久化数据和顺序启动的场景。如果你的应用是无状态的(如 Web 服务),Deployment 是更合适的选择;但如果你需要运行数据库或类似的服务,StatefulSet 就是最优解。
