部署kubernetes集群和POD持久化存储storageclass

1、部署1master 3node四节点kubernetes集群。

1.1 环境准备

系统环境:rocky 8.5

kubernetes版本:v1.28.2

主机数量:4(1master,3node):10.0.0.133 master,10.0.0.136 node1,10.0.0.137 node2,10.0.0.138 node3

设置时间同步,所有主机时间相同

关闭防火墙、SElinux、SWAP

禁用SWAP

[root@Rocky8 ~]# swapoff -a 关闭当前已启用的所有Swap设备
[root@Rocky8 ~]# cat /etc/fstab 注释用于挂载Swap设备的所有行 重启主机
/dev/mapper/rl-root     /                       xfs     defaults        0 0
UUID=600d39a7-f5d0-4ad6-b24f-13bfa845839e /boot                   xfs     defaults        0 0
/dev/mapper/rl-home     /home                   xfs     defaults        0 0
#/dev/mapper/rl-swap     none                    swap    defaults        0 0

在所有主机上添加以下hots解析:

出于简化配置步骤的目的,本测试环境使用hosts文件进行各节点名称解析,文件内容如下所示。其中,我们使用kubeapi主机名作为API Server在高可用环境中的专用接入名称,也为控制平面的高可用配置留下便于配置的余地。

10.0.0.133  k8s-master01.xinqi66.com k8s-master01 kubeapi.xinqi66.com kubeapi
10.0.0.136  k8s-node01.xinqi66.com k8s-node01
10.0.0.137  k8s-node02.xinqi66.com k8s-node02
10.0.0.138  k8s-node03.xinqi66.com k8s-node03

注意:下列操作中某些操作需要下载github上的资源需要使用到代理,需提前准备。

1.2 安装docker

以下操作在所有节点下执行:

生成docker-ce相关程序包的仓库,这里以阿里云的镜像服务器为例进行说明:

cat >  /etc/yum.repos.d/docker.repo  <<EOF
[docker]
name=docker
gpgcheck=0
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/
EOF

接着,安装相关的程序包,Rocky8.5上要使用的程序包名称为docker-ce:

yum -y install docker-ce-24.0.6 docker-ce-cli-24.0.6

kubelet需要让docker容器引擎使用systemd作为CGroup的驱动,其默认值为cgroupfs,因而,我们还需要编辑docker的配置文件/etc/docker/daemon.json,添加如下内容,其中的registry-mirrors用于指明使用的镜像加速服务。

{
"registry-mirrors": [
  "https://registry.docker-cn.com"
],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
  "max-size": "200m"
},
"storage-driver": "overlay2"  
}

1.3 安装cri-dockerd

以下操作在所有节点下执行:

Kubernetes自v1.24移除了对docker-shim的支持,而Docker Engine默认又不支持CRI规范,因而二者将无法直接完成整合。为此,Mirantis和Docker联合创建了cri-dockerd项目,用于为Docker Engine提供一个能够支持到CRI规范的垫片,从而能够让Kubernetes基于CRI控制Docker 。

curl -LO https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.4/cri-dockerd-0.3.4-3.el8.x86_64.rpm

yum -y install cri-dockerd-0.3.4-3.el8.x86_64.rpm
systemctl enable --now cri-docker.service

1.4 安装kubelet、kubeadm和kubectl

以下操作在所有节点下执行:

在各主机上生成kubelet和kubeadm等相关程序包的仓库,并安装kubelet kubeadm kubectl。这里以阿里云的镜像服务为例:

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
setenforce 0
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet

1.5 配置cri-dockerd

以下操作在所有节点下执行:

配置cri-dockerd,确保其能够正确加载到CNI插件。编辑/usr/lib/systemd/system/cri-docker.service文件,确保其[Service]配置段中的ExecStart的值类似如下内容。

ExecStart=/usr/bin/cri-dockerd
 --container-runtime-endpoint fd:// --network-plugin=cni 
--cni-bin-dir=/opt/cni/bin --cni-cache-dir=/var/lib/cni/cache 
--cni-conf-dir=/etc/cni/net.d --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.9

需要添加的各配置参数(各参数的值要与系统部署的CNI插件的实际路径相对应):

  • –network-plugin:指定网络插件规范的类型,这里要使用CNI;
  • –cni-bin-dir:指定CNI插件二进制程序文件的搜索目录;
  • –cni-cache-dir:CNI插件使用的缓存目录;
  • –cni-conf-dir:CNI插件加载配置文件的目录;
  • –pod-infra-container-image: 添加阿里镜像代理

配置完成后,重载并重启cri-docker.service服务。

~# systemctl daemon-reload && systemctl restart cri-docker.service

1.6 初始化第一个主节点

该步骤开始尝试构建Kubernetes集群的master节点,配置完成后,各worker节点直接加入到集群中的即可。需要特别说明的是,由kubeadm部署的Kubernetes集群上,集群核心组件kube-apiserver、kube-controller-manager、kube-scheduler和etcd等均会以静态Pod的形式运行,它们所依赖的镜像文件默认来自于registry.k8s.io这一Registry服务之上。但我们无法直接访问该服务,常用的解决办法有如下两种,本示例将选择使用更易于使用的前一种方式。

  • 使用能够到达该服务的代理服务;
  • 使用国内的镜像服务器上的服务,例如registry.aliyuncs.com/google_containers等。
1.6.1初始化master节点(在master01上完成如下操作)

在运行初始化命令之前先运行如下命令单独获取相关的镜像文件,而后再运行后面的kubeadm init命令,以便于观察到镜像文件的下载过程。

~# kubeadm config images list --image-repository=registry.aliyuncs.com/google_containers

上面的命令会列出类似如下的Image信息。

[root@Rocky8 ~]# kubeadm config images list --image-repository=registry.aliyuncs.com/google_containers
registry.aliyuncs.com/google_containers/kube-apiserver:v1.28.2
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.28.2
registry.aliyuncs.com/google_containers/kube-scheduler:v1.28.2
registry.aliyuncs.com/google_containers/kube-proxy:v1.28.2
registry.aliyuncs.com/google_containers/pause:3.9
registry.aliyuncs.com/google_containers/etcd:3.5.9-0
registry.aliyuncs.com/google_containers/coredns:v1.10.1

运行下面的命令即可下载需要用到的各Image。需要注意的是,如果需要从国内的Mirror站点下载Image,同样需要在命令上使用“–image-repository”选项来指定Mirror站点的相关URL。

kubeadm config images pull --cri-socket unix:///run/cri-dockerd.sock --image-repository=registry.aliyuncs.com/google_containers

[root@Rocky8 ~]# kubeadm config images pull --cri-socket unix:///run/cri-dockerd.sock --image-repository=registry.aliyuncs.com/google_containers
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.28.2
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.28.2
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.28.2
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.28.2
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.9
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.5.9-0
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:v1.10.1
1.6.2 初始化方式

运行如下命令完成k8s-master01节点的初始化:

kubeadm init --control-plane-endpoint="kubeapi.xinqi66.com" --kubernetes-version=v1.28.2 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --token-ttl=0  --cri-socket unix:///run/cri-dockerd.sock --upload-certs --image-repository=registry.aliyuncs.com/google_containers

命令中的各选项简单说明如下:

  • –image-repository:指定要使用的镜像仓库,默认为registry.k8s.io;

  • –kubernetes-version:kubernetes程序组件的版本号,它必须要与安装的kubelet程序包的版本号相同;

  • –control-plane-endpoint:控制平面的固定访问端点,可以是IP地址或DNS名称,会被用于集群管理员及集群组件的kubeconfig配置文件的API Server的访问地址;单控制平面部署时可以不使用该选项;

  • –pod-network-cidr:Pod网络的地址范围,其值为CIDR格式的网络地址,通常,Flannel网络插件的默认为10.244.0.0/16,Project Calico插件的默认值为192.168.0.0/16;

  • –service-cidr:Service的网络地址范围,其值为CIDR格式的网络地址,默认为10.96.0.0/12;通常,仅Flannel一类的网络插件需要手动指定该地址;

  • –apiserver-advertise-address:apiserver通告给其他组件的IP地址,一般应该为Master节点的用于集群内部通信的IP地址,0.0.0.0表示节点上所有可用地址;

  • –token-ttl:共享令牌(token)的过期时长,默认为24小时,0表示永不过期;为防止不安全存储等原因导致的令牌泄露危及集群安全,建议为其设定过期时长。未设定该选项时,在token过期后,若期望再向集群中加入其它节点,可以使用如下命令重新创建token,并生成节点加入命令。

    kubeadm token create --print-join-command
    

提示:无法访问registry.k8s.io时,同样可以在上面的命令中使用“–image-repository=registry.aliyuncs.com/google_containers”选项,以便从国内的镜像服务中获取各Image;

注意:若各节点未禁用Swap设备,还需要附加选项“–ignore-preflight-errors=Swap”,从而让kubeadm忽略该错误设定;

1.6.3 初始化完成后的操作步骤

对于Kubernetes系统的新用户来说,无论使用上述哪种方法,命令运行结束后,请记录最后的kubeadm join命令输出的最后提示的操作步骤。下面的内容是需要用户记录的一个命令输出示例,它提示了后续需要的操作步骤。

# 下面是成功完成第一个控制平面节点初始化的提示信息及后续需要完成的步骤
Your Kubernetes control-plane has initialized successfully!

# 为了完成初始化操作,管理员需要额外手动完成几个必要的步骤
To start using your cluster, you need to run the following as a regular user:

# 第1个步骤提示, Kubernetes集群管理员认证到Kubernetes集群时使用的kubeconfig配置文件
  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 我们也可以不做上述设定,而使用环境变量KUBECONFIG为kubectl等指定默认使用的
Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

# 第2个步骤提示,为Kubernetes集群部署一个网络插件,具体选用的插件则取决于管理员;
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

# 第3个步骤提示,向集群添加额外的控制平面节点,但本文会略过该步骤,并将在其它文章介绍其实现方式。
You can now join any number of the control-plane node running the following command on each as root:

# 在部署好kubeadm等程序包的其他控制平面节点上以root用户的身份运行类似如下命令,
# 命令中的hash信息对于不同的部署环境来说会各不相同;该步骤只能在其它控制平面节点上执行;
# 提示:与cri-dockerd结合使用docker-ce作为container runtime时,通常需要为下面的命令
#     额外附加“--cri-socket unix:///run/cri-dockerd.sock”选项;
  kubeadm join kubeapi.xinqi66.com:6443 --token pi6jw8.kw6v0yve1oh27tzo \
	--discovery-token-ca-cert-hash sha256:3875d8752584004225ddb0879ab27f494aac0d2e05b7380de2f59d30bb312953 \
	--control-plane --certificate-key f9073b6dba6643e20d683b6cd7361d3881a030836f596e630ac90d1c3ba70e9b \
	--cri-socket unix:///run/cri-dockerd.sock

# 因为在初始化命令“kubeadm init”中使用了“--upload-certs”选项,因而初始化过程会自动上传添加其它Master时用到的数字证书等信息;
# 出于安全考虑,这些内容会在2小时之后自动删除;
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.

# 第4个步骤提示,向集群添加工作节点
Then you can join any number of worker nodes by running the following on each as root:

# 在部署好kubeadm等程序包的各工作节点上以root用户运行类似如下命令;
# 提示:与cri-dockerd结合使用docker-ce作为container runtime时,通常需要为下面的命令
#     额外附加“--cri-socket unix:///run/cri-dockerd.sock”选项;
kubeadm join kubeapi.xinqi66.com:6443 --token pi6jw8.kw6v0yve1oh27tzo \
	--discovery-token-ca-cert-hash sha256:3875d8752584004225ddb0879ab27f494aac0d2e05b7380de2f59d30bb312953 \
	--cri-socket unix:///run/cri-dockerd.sock

1.7 设定kubectl

kubectl是kube-apiserver的命令行客户端程序,实现了除系统部署之外的几乎全部的管理操作,是kubernetes管理员使用最多的命令之一。kubectl需经由API server认证及授权后方能执行相应的管理操作,kubeadm部署的集群为其生成了一个具有管理员权限的认证配置文件/etc/kubernetes/admin.conf,它可由kubectl通过默认的“$HOME/.kube/config”的路径进行加载。当然,用户也可在kubectl命令上使用–kubeconfig选项指定一个别的位置。

下面复制认证为Kubernetes系统管理员的配置文件至目标用户(例如当前用户root)的家目录下:

~# mkdir ~/.kube

~# cp /etc/kubernetes/admin.conf ~/.kube/config

1.8 部署网络插件

Kubernetes系统上Pod网络的实现依赖于第三方插件进行,这类插件有近数十种之多,较为著名的有flannel、calico、canal和kube-router等,简单易用的实现是为CoreOS提供的flannel项目。下面的命令用于在线部署flannel至Kubernetes系统之上,我们需要在初始化的第一个master节点k8s-master01上运行如下命令,以完成部署。

~# kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

而后使用如下命令确认其输出结果中Pod的状态为“Running”,类似如下命令及其输入的结果所示:

~# kubectl get pods -n kube-flannel

上述命令应该会得到类似如下输出,这表示kube-flannel已然正常运行。

NAME                    READY   STATUS    RESTARTS   AGE
kube-flannel-ds-d9jht   1/1     Running   0          2m55s

1.9 验证master节点已经就绪

~# kubectl get nodes

上述命令应该会得到类似如下输出,这表示k8s-master01节点已经就绪。

[root@k8s-master01 ~]# kubectl get nodes
NAME                       STATUS   ROLES           AGE   VERSION
k8s-master01.xinqi66.com   Ready    control-plane   33m   v1.28.2

1.10 添加节点到集群中

下面的两个步骤,需要分别在k8s-node01、k8s-node02和k8s-node03上各自完成。

1、若未禁用Swap设备,编辑kubelet的配置文件/etc/default/kubelet,设置其忽略Swap启用的状态错误,内容如下:KUBELET_EXTRA_ARGS=“–fail-swap-on=false”

2、将节点加入第二步中创建的master的集群中,要使用主节点初始化过程中记录的kubeadm join命令;

[root@k8s-node01 ~]# kubeadm join kubeapi.xinqi66.com:6443 --token pi6jw8.kw6v0yve1oh27tzo \
> --discovery-token-ca-cert-hash sha256:3875d8752584004225ddb0879ab27f494aac0d2e05b7380de2f59d30bb312953 \
> --cri-socket unix:///run/cri-dockerd.sock
[preflight] Running pre-flight checks
	[WARNING FileExisting-tc]: tc not found in system path
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

1.11 验证节点添加结果

在每个节点添加完成后,即可通过kubectl验证添加结果。下面的命令及其输出是在所有的三个节点均添加完成后运行的,其输出结果表明三个Worker Node已经准备就绪。

~# kubectl get nodes

[root@k8s-master01 ~]# kubectl get nodes
NAME                       STATUS   ROLES           AGE     VERSION
k8s-master01.xinqi66.com   Ready    control-plane   41m     v1.28.2
k8s-node01.xinqi66.com     Ready    <none>          4m23s   v1.28.2
k8s-node02.xinqi66.com     Ready    <none>          106s    v1.28.2
k8s-node03.xinqi66.com     Ready    <none>          99s     v1.28.2
初始化失败,重置集群命令:
kubeadm reset --cri-socket unix:///run/cri-dockerd.sock && rm -rf /etc/kubernetes/ /var/lib/kubelet /var/lib/dockershim /var/run/kubernetes /var/lib/cni /etc/cni/net.d
提示:先重置工作节点,再重置主节点;

1.12 测试应用编排及服务访问

到此为止,一个master,并附带有三个worker的kubernetes集群基础设施已经部署完成,用户随后即可测试其核心功能。例如,下面的命令可将demoapp以Pod的形式编排运行于集群之上,并通过在集群外部进行访问:

~# kubectl create deployment demoapp --image=ikubernetes/demoapp:v1.0 --replicas=3

~# kubectl create service nodeport demoapp --tcp=80:80

而后,使用如下命令了解Service对象demoapp使用的NodePort,以便于在集群外部进行访问:

~# kubectl get svc -l app=demoapp

[root@k8s-master01 ~]# kubectl get svc -l app=demoapp  
NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
demoapp   NodePort   10.105.158.92   <none>        80:32511/TCP   6s

demoapp是一个web应用,因此,用户可以于集群外部通过“http://NodeIP:31009”这个URL访问demoapp上的应用,例如于集群外通过浏览器访问“http://172.29.1.11:31009”。

我们也可以在Kubernetes集群上启动一个临时的客户端,对demoapp服务发起访问测试。

~# kubectl run client-$RANDOM --image=ikubernetes/admin-box:v1.2 --rm --restart=Never -it --command – /bin/bash

而后,在打开的交互式接口中,运行如下命令,对demoapp.default.svc服务发起访问请求,验证其负载均衡的效果。

root@client-5229 ~# while true; do curl demoapp.default.svc; sleep 1; done

该命令会持续返回类似如下的结果,这可以证明CoreDNS名称解析功能,以及Service的服务发现及负载均衡功能均已经正常工作。

[root@k8s-master01 ~]# kubectl run client-$RANDOM --image=ikubernetes/admin-box:v1.2 --rm --restart=Never -it --command -- /bin/bash
If you don't see a command prompt, try pressing enter.
root@client-16593 /# while true; do curl demoapp.default.svc; sleep 1; done
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.3, ServerName: demoapp-7c58cd6bb-shvqq, ServerIP: 10.244.1.2!
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.3, ServerName: demoapp-7c58cd6bb-wsfdb, ServerIP: 10.244.2.2!
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.3, ServerName: demoapp-7c58cd6bb-wsfdb, ServerIP: 10.244.2.2!
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.3, ServerName: demoapp-7c58cd6bb-wsfdb, ServerIP: 10.244.2.2!
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.3, ServerName: demoapp-7c58cd6bb-wsfdb, ServerIP: 10.244.2.2!
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.3, ServerName: demoapp-7c58cd6bb-wsfdb, ServerIP: 10.244.2.2!
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.3, ServerName: demoapp-7c58cd6bb-wsfdb, ServerIP: 10.244.2.2!
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.3, ServerName: demoapp-7c58cd6bb-xgltn, ServerIP: 10.244.3.2!
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.3, ServerName: demoapp-7c58cd6bb-wsfdb, ServerIP: 10.244.2.2!
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.3, ServerName: demoapp-7c58cd6bb-xgltn, ServerIP: 10.244.3.2!

运行下面的命令,完成测试应用的清理。

~# kubectl delete deployments/demoapp services/demoapp

2、使用NFS做pod持久化存储。

2.1 使用PVC和PV卷实现pod存储持久化
PV概念

PersistentVolume(PV)是集群中已由管理员配置的一段网络存储。集群中的资源就像一个节点是一个集群资源,可以从远程的NFS或分布式对象存储系统中创建得来(pv存储空间大小、访问方式)
Pv是诸如卷之类的卷插件,但是只有独立于使用Pv的任何单个pod的生命周期。
该API对象捕获存储的实现细节,即NFS,isCSI或云提供商特定的存储系统
PV就是从存储设备中的空间创建出一个存储资源

PVC概念

PersistentVolumeClaim (Pvc)是用户存储的请求。Pvc的使用逻辑:在podt中定义一个存储卷(该存储卷类型为pvc),定义的时候直按指定大小,pvc必须与对应的pv建立关系,pvc会根据定义去pv申请,而pv是由存储空间创建出来的。pr和pvc是kubernetes抽象出来的一种存储资源
虽然PersistentVolumeClaims允许用户使用抽象存储资源,但是常见的需求是,用户需要根据不同的需求去创建v,用于不同的场景。而此时需要集群管理员提供不同需求的Pv,而不仅仅是Pv的大小和访问模式,但又不需要用户了解这些卷的实现细节
对于这样的需求,此时可以采用storageclass资源
PV与PVC之间的关系
PVv是集群中的资源。Pvc是对这些资源的请求,也是对资源的索引检查。PV和Pvc之间的相互作用遵循这个生命周期:Provisioning(配置)—> Binding(绑定)—>Using(使用)—>Releasing(释放)—>Recycling(回收)
————————————————

2.2 基于静态创建PV,PVC并使用NFS共享存储
部署nfs服务器
yum install nfs-utils -y
mkdir /data/volumes/v{1..3} -p

vim /etc/exports
/data/volumes/v1 *(rw,no_root_squash)
/data/volumes/v2 *(rw,no_root_squash)
/data/volumes/v3 *(rw,no_root_squash)

#加载配置生效 && 启动NFS服务
exportfs -arv
systemctl enable --now nfs-server.service
在master和所有node节点上安装nfsb并设置为开机启动
yum install -y nfs-utils
systemctl enable --now nfs-server.service
编辑以下三个yaml文件,并创建。
PV配置:pv-mysql.yaml
apiVersion: v1
kind: PersistentVolume  # 声明一个持久卷
metadata: 
  name: pv-nfs  # 卷的名称
spec:
  capacity:
    storage: 10Gi  # 定义卷的容量为10GiB
  volumeMode: Filesystem  # 卷的模式为文件系统
  accessModes:
    - ReadWriteMany  # 支持多节点读写
  persistentVolumeReclaimPolicy: Retain  # 持久卷回收策略为保留
  mountOptions:
    - hard  # 使用硬挂载
    - nfsvers=4.1  # NFS版本为4.1
  nfs:
    path: "/data/mysql1"  # NFS服务器上的路径
    server: 10.0.0.139  # NFS服务器的IP地址
PVC配置:pvc-mysql.yaml:
apiVersion: v1
kind: PersistentVolumeClaim  # 声明一个持久卷索赔
metadata:
  name: pvc-mysql  # 索赔的名称
spec:
  accessModes:
    - ReadWriteMany  # 支持多节点读写
  volumeMode: Filesystem  # 卷的模式为文件系统
  resources:
    requests:
      storage: 8Gi  # 请求8GiB的存储容量
    limits:
      storage: 15Gi  # 设置存储容量上限为15GiB
MYSQL配置:mysql.yaml
apiVersion: v1
kind: Pod  # 创建一个Pod
metadata:
  name: mydb  # Pod的名称
  labels:
    app: mydb  # 标签为"app: mydb"
spec:
  containers:
  - name: mydb  # 容器的名称
    image: mysql:8.0  # 使用MySQL 8.0镜像
    env:
    - name: MYSQL_RANDOM_ROOT_PASSWORD  # 设置MySQL的环境变量
      value: 1
    - name: MYSQL_DATABASE
      value: wpdb
    - name: MYSQL_USER
      value: wpuser
    - name: MYSQL_PASSWORD
      value: xinqi
    volumeMounts:
    - name: mysql-nfs-vol  # 挂载的卷名称
      mountPath: /var/lib/mysql  # 挂载路径
  volumes:
  - name: mysql-nfs-vol  # 卷的名称
    persistentVolumeClaim:
      claimName: pvc-mysql  # 使用名为pvc-mysql的持久卷索赔
使用apply命令依次创建pv,pvc,mysql
kubectl apply -f pv-mysql.yaml
kubectl apply -f pvc-mysql.yaml
kubectl apply -f mysql.yaml
查看pv,pvc状态,卷已被挂载。
[root@k8s-master01 yaml]# kubectl get pv 
NAME          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
pv-nfs   10Gi       RWX            Retain           Bound    default/pvc-mysql                           21m
[root@k8s-master01 yaml]# kubectl get pvc
NAME        STATUS   VOLUME        CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-mysql   Bound    pv-nfs-demo   10Gi       RWX                           21m
查看nfs共享存储上的mysql1目录是否已经写入数据
[root@Rocky8 /]# ll /data/mysql1
total 198056
-rw-r----- 1 systemd-coredump input       56 Oct 17 09:47  auto.cnf
-rw-r----- 1 systemd-coredump input  3117676 Oct 17 09:47  binlog.000001
-rw-r----- 1 systemd-coredump input      156 Oct 17 09:47  binlog.000002
-rw-r----- 1 systemd-coredump input       32 Oct 17 09:47  binlog.index
-rw------- 1 systemd-coredump input     1676 Oct 17 09:47  ca-key.pem
-rw-r--r-- 1 systemd-coredump input     1112 Oct 17 09:47  ca.pem
-rw-r--r-- 1 systemd-coredump input     1112 Oct 17 09:47  client-cert.pem
-rw------- 1 systemd-coredump input     1680 Oct 17 09:47  client-key.pem
-rw-r----- 1 systemd-coredump input   196608 Oct 17 09:49 '#ib_16384_0.dblwr'
-rw-r----- 1 systemd-coredump input  8585216 Oct 17 09:47 '#ib_16384_1.dblwr'
-rw-r----- 1 systemd-coredump input     5695 Oct 17 09:47  ib_buffer_pool
-rw-r----- 1 systemd-coredump input 12582912 Oct 17 09:47  ibdata1
-rw-r----- 1 systemd-coredump input 50331648 Oct 17 09:49  ib_logfile0
-rw-r----- 1 systemd-coredump input 50331648 Oct 17 09:47  ib_logfile1
-rw-r----- 1 systemd-coredump input 12582912 Oct 17 09:48  ibtmp1
drwxr-x--- 2 systemd-coredump input      187 Oct 17 09:47 '#innodb_temp'
drwxr-x--- 2 systemd-coredump input      143 Oct 17 09:47  mysql
-rw-r----- 1 systemd-coredump input 31457280 Oct 17 09:47  mysql.ibd
drwxr-x--- 2 systemd-coredump input     8192 Oct 17 09:47  performance_schema
-rw------- 1 systemd-coredump input     1676 Oct 17 09:47  private_key.pem
-rw-r--r-- 1 systemd-coredump input      452 Oct 17 09:47  public_key.pem
-rw-r--r-- 1 systemd-coredump input     1112 Oct 17 09:47  server-cert.pem
-rw------- 1 systemd-coredump input     1680 Oct 17 09:47  server-key.pem
drwxr-x--- 2 systemd-coredump input       28 Oct 17 09:47  sys
-rw-r----- 1 systemd-coredump input 16777216 Oct 17 09:49  undo_001
-rw-r----- 1 systemd-coredump input 16777216 Oct 17 09:49  undo_002
drwxr-x--- 2 systemd-coredump input        6 Oct 17 09:47  wpdb
删除mysql,pvc和pv后,在NFS上查看数据依旧存在。
kubectl delete -f mysql.yaml
kubectl delete -f pvc-mysql.yaml
kubectl delete -f pv-mysql.yaml
三. 基于动态 storageclass 创建 PV、PVC
3.1 storageclass 定义

前面的例子中,我们提前创建了 PV,然后通过 PVC 申请 PV 并在 Pod 中使用,这种方式叫做静态供给(Static Provision)。
与之对应的是动态供给(Dynamical Provision),即如果没有满足 PVC 条件的 PV,会动态创建 PV。相比静态供给,动态供给有明显的优势:不需要提前创建 PV,减少了管理员的工作量,效率高。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.2 storageclass 用途

在 PV 和 PVC 使用过程中存在的问题,在 PVC 申请存储空间时,未必就有现成的 PV 符合 PVC 申请的需求,上面 nfs 在做 PVC 可以成功的因素是因为我们做了指定的需求处理。当 PVC 申请的存储空间不一定有满足 PVC 要求的 PV 时,Kubernetes 为管理员提供了描述存储 “class(类)” 的方法(StorageClass)。
举个例子,在存储系统中划分一个 1TB 的存储空间提供给 Kubernetes 使用,当用户需要一个 10G 的 PVC 时,会立即通过 restful 发送请求,从而让存储空间创建一个 10G 的 image,之后在我们的集群中定义成 10G 的 PV 供给给当前的 PVC 作为挂载使用。在此之前我们的存储系统必须支持 restful 接口,比如 ceph 分布式存储,而 glusterfs 则需要借助第三方接口完成这样的请求。

因为NFS不支持动态存储,所以我们需要借用这个存储插件。
nfs动态相关部署可以参考:https://github.com/kubernetes-csi/csi-driver-nfs

参考部署文档:https://github.com/iKubernetes/learning-k8s/tree/master/csi-driver-nfs

3.3.1部署csi-driver-nfs
kubectl apply -f https://github.com/slcnx/tekton-and-argocd-in-practise/tree/main/nfs-csi-driver/nfs-driver
检查pod状态
kubectl -n kube-system get pod -o wide -l 'app in (csi-nfs-node,csi-nfs-controller)'
pod部署成功
NAME                                  READY   STATUS    RESTARTS   AGE   IP           NODE                       NOMINATED NODE   READINESS GATES
csi-nfs-controller-7685644675-bcccf   4/4     Running   0          74m   10.0.0.138   k8s-node03.xinqi66.com     <none>           <none>
csi-nfs-node-7w7l6                    3/3     Running   0          74m   10.0.0.133   k8s-master01.xinqi66.com   <none>           <none>
csi-nfs-node-99xvk                    3/3     Running   0          74m   10.0.0.137   k8s-node02.xinqi66.com     <none>           <none>
csi-nfs-node-f8wlt                    3/3     Running   0          74m   10.0.0.138   k8s-node03.xinqi66.com     <none>           <none>
csi-nfs-node-tmpgh                    3/3     Running   0          74m   10.0.0.136   k8s-node01.xinqi66.com     <none>           <none>
创建storage class
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-csi
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: nfs.csi.k8s.io
parameters:
  server: 10.0.0.139 #NFS地址
  share: /data/mysql2 #共享目录
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
  - hard
  - nfsvers=4.1
若需要在创建完StorageClass后将其设置为默认,可使用类似如下命令进行。
kubectl patch storageclass nfs-csi -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

取消某StorageClass的默认设定,则将类似上面命令中的annotation的值修改为false即可。

创建一个PVC进行测试
kubectl create -f sc-pvc-nfs.yaml

[root@k8s-master01 yaml]# cat sc-pvc-nfs.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs-dynamic
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: nfs-csi

查看PV已经自动创建.

[root@k8s-master01 yaml]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS   REASON   AGE
pvc-8be20ce4-34a0-4d64-ba4a-1ee9ec3bb3b9   10Gi       RWX            Delete           Bound    default/pvc-nfs-dynamic   nfs-csi                 25m
创建MYSQL pod,使用pvc。
kubectl create -f mysql.yaml

[root@k8s-master01 mysql]# cat mysql.yaml 
apiVersion: v1  
kind: Pod  
metadata:  
  name: mydb  
  labels:  
    app: mydb  
spec:  
  containers:  
  - name: mydb  
    image: mysql:8.0  
    env:  
    - name: MYSQL_RANDOM_ROOT_PASSWORD  
      value: xq  
    - name: MYSQL_DATABASE  
      value: wpdb  
    - name: MYSQL_USER  
      value: wpuser  
    - name: MYSQL_PASSWORD  
      value: xinqi
    volumeMounts:
    - name: mysql-nfs-vol
      mountPath: /var/lib/mysql
  volumes:
  - name: mysql-nfs-vol
    persistentVolumeClaim:
      claimName: pvc-nfs-dynamic
查看NFS服务器,数据目录,数据以及存储到服务器上
[root@NFS.xinqi66 data]# ll mysql2/pvc-8be20ce4-34a0-4d64-ba4a-1ee9ec3bb3b9/
total 198056
-rw-r----- 1 systemd-coredump input       56 Oct 19 11:02  auto.cnf
-rw-r----- 1 systemd-coredump input  3117675 Oct 19 11:02  binlog.000001
-rw-r----- 1 systemd-coredump input      156 Oct 19 11:02  binlog.000002
-rw-r----- 1 systemd-coredump input       32 Oct 19 11:02  binlog.index
-rw------- 1 systemd-coredump input     1680 Oct 19 11:02  ca-key.pem
-rw-r--r-- 1 systemd-coredump input     1112 Oct 19 11:02  ca.pem
-rw-r--r-- 1 systemd-coredump input     1112 Oct 19 11:02  client-cert.pem
-rw------- 1 systemd-coredump input     1676 Oct 19 11:02  client-key.pem
-rw-r----- 1 systemd-coredump input   196608 Oct 19 11:04 '#ib_16384_0.dblwr'
-rw-r----- 1 systemd-coredump input  8585216 Oct 19 11:02 '#ib_16384_1.dblwr'
....

d-coredump input 56 Oct 19 11:02 auto.cnf
-rw-r----- 1 systemd-coredump input 3117675 Oct 19 11:02 binlog.000001
-rw-r----- 1 systemd-coredump input 156 Oct 19 11:02 binlog.000002
-rw-r----- 1 systemd-coredump input 32 Oct 19 11:02 binlog.index
-rw------- 1 systemd-coredump input 1680 Oct 19 11:02 ca-key.pem
-rw-r–r-- 1 systemd-coredump input 1112 Oct 19 11:02 ca.pem
-rw-r–r-- 1 systemd-coredump input 1112 Oct 19 11:02 client-cert.pem
-rw------- 1 systemd-coredump input 1676 Oct 19 11:02 client-key.pem
-rw-r----- 1 systemd-coredump input 196608 Oct 19 11:04 ‘#ib_16384_0.dblwr’
-rw-r----- 1 systemd-coredump input 8585216 Oct 19 11:02 ‘#ib_16384_1.dblwr’


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值