指尖上的记忆指尖上的记忆
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub

使用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 就是最优解。