安装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 就是最优解。
