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

安装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常规命令

删除集群
  
查看集群的节点:
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 /etc/docker/daemon.json

{
"registry-mirrors": [
"https://docker.1ms.run"
],
"proxies": {
    "http-proxy": "http://127.0.0.1:7890",
    "https-proxy": "http://127.0.0.1:7890",
    "no-proxy": "localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
  }
}

这样可以直接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
不需要在这里配置: vim ~/.docker/config.json

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