RC、RS、Deployment 可以控制副本数量,但需要所有 Pod 副本使用的数据与 Pod 自身的生命周期分离,这就需要用额外的空间存储这些数据。
PV(Persistent Volume),是一个全局资源,在创建之初定义了有多大的存储能力。
PVC(Persistent Volume Claim),是 Namespace 中的资源,描述的是对 PV 的一个使用请求。
每个需要使用的 Pod 需要有一个 PVC 与全局的 PV 相绑定,并且声明自己使用 PV 的多大空间。
安装 nfs
每个节点需要有 nfs 的客户端,nfs 的服务端可以只有一个。(C/S模式)
yum install nfs-utils -y # 所有节点安装客户端
配置 nfs 访问
以下配置,共享 /data 目录,使用 192.168.208.0/24 段访问,读写,同步、指定不做 root 用户的 uid 映射,不做其他用户的 uid 映射。
# vim /etc/exports
/data 192.168.208.0/24(rw,async,no_root_squash,no_all_squash) #
重启 rpcbind 和 nfs
systemctl restart rpcbind
systemctl restart nfs #
systemctl enable nfs # 记得设置为开机自启动
nfs 启动状态错误
image.png
原来是因为括号中是逗号而不是空格,教程上没体现到变动。以上代码已经是修正版的了
验证安装成功
在任何一台机器上通过 showmount -e 192.168.208.130
查看是否能查到 nfs。
创建 pv
# pv/test-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: test
labels:
type: test
spec:
capacity:
storage: 10Gi # 提供 10G 的存储
accessModes:
- ReadWriteMany # 允许多个 Pod 同时读写
persistentVolumeReclaimPolicy: Recycle # pvc 的策略,允许回收
nfs:
path: "/data/k8s"
server: 192.168.208.130 #
readOnly: false # 取消只读,就是可写
kubectl create -f pv/test-pv.yml # persistentvolume "test" created
以下通过更改名字和空间大小,创建了三个 pv,查看 pv:
image.png创建 pvc
# test-pvc.yml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs # pvc 的名字
spec:
accessModes:
- ReadWriteMany # 模式允许多人读写访问
resources:
requests:
storage: 1Gi # 需求资源 1G
image.png
更新 pvc 请求资源量,pvc 会对应使用容量最小能用的 pv 进行绑定。
image.png实践 Pod 使用 nfs pv/pvc
- 写了一个向服务器文件目录中上传文件以及获取文件列表的程序
- 创建 k8s 资源配置文件,使用 pv、pvc、svc、deployment 资源
- 通过 postman 上传文件,通过浏览器查看列表
制作程序:显示文件列表及上传文件
用 go 写一个提供上传/访问文件系统的程序,代码如下:
package main
import (
// ...
"github.com/gin-gonic/gin"
)
var (
filedir = flag.String("d", "./data", "the file dir for server")
port = flag.String("p", "8080", "the port which server is running on")
)
func main() {
flag.Parse()
abs, err := filepath.Abs(*filedir)
if err != nil {
abs = *filedir
}
fmt.Println("the file dir:", abs)
fmt.Println("runing on port:", *port)
fmt.Println()
app := gin.New()
app.GET("/", func(c *gin.Context) {
c.Redirect(301, "/fs")
})
app.StaticFS("/fs", gin.Dir(*filedir, true)) // API:列表指定目录的内容
app.POST("/upload", func(c *gin.Context) { // API 上传文件
datafile, header, err := c.Request.FormFile("datafile")
if err != nil {
c.AbortWithError(400, err)
return
}
defer datafile.Close()
fd, err := os.Create(filepath.Join(*filedir, header.Filename))
if err != nil {
c.AbortWithError(500, err)
return
}
defer fd.Close()
io.Copy(fd, datafile)
})
if err := app.Run(":" + *port); err != nil {
fmt.Println("service run failed:", err.Error())
}
}
使用 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build .
交叉编译出 linux 上二进制文件。(输出 fs-svr)
构建 Docker
创建 Dockerfile:
FROM 192.168.208.130:5000/alpine:latest
COPY fs-svr /service/
WORKDIR /service
RUN mkdir /data /service/data # RUN 在 build 阶段执行
EXPOSE 9000
ENTRYPOINT ["./fs-svr"] # ENTRYPOINT 的命令在 run 阶段执行,可以和 CMD 拼接到一块
CMD ["-p", "9000", "-d", "/data"] # CMD 在 run 阶段执行,可以认为是默认的启动命令/参数,可以被传入的命令/参数覆盖
注意:
这里使用 alpine 作为基础镜像,注意先从网上下载这个基础镜像,然后改 tag 推到私有镜像库中。
这里用服务名为 fs-svr,并且在服务本地目录位置有个 data 目录是服务内部默认用的目录
通过一系列操作将镜像构建出来并 push 到私有库中:
docker build . # 构建
docker tag 676d70bef0a7 192.168.208.130:5000/fs-svr:0.0.1 # 打私有仓库的标签
docker push 192.168.208.130:5000/fs-svr:0.0.1 # 提交到私有仓库
创建 k8s 资源
编辑 k8s.yml 文件。创建 deployment 和 service 资源
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: fs-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: fs-svr
spec:
containers:
- name: fs-svr
image: 192.168.208.130:5000/fs-svr:0.0.1
ports:
- containerPort: 9000
volumeMounts:
- name: fsdata # 绑定 template 定义的 volumes
mountPath: /data/
volumes: # 与 containers 并级
- name: fsdata # 自定义一个名称,必须小写,用于 containers[].volumeMounts[].name
persistentVolumeClaim: #
claimName: nfs2 # 使用的 pvc 的名字
---
apiVersion: v1
kind: Service # 创建 service,允许通过宿主机访问
metadata:
name: fs-service
spec:
type: NodePort # 端口映射的方式,还有其他支持
ports:
- port: 80 # cluster IP 的端口
nodePort: 30000 # 宿主机的端口(宿主机的端口在配置文件中指定)
targetPort: 9000 # pod 地址的端口
selector: # 为哪些 Pod 做负载均衡是通过标签选择器选择的
app: fs-svr # 选择 app: fs-svr 的 Label
通过 kubectl create -f k8s.yaml
创建资源。创建的资源列表:
测试上传和显示
- 通过浏览器地址
http://k8s-master:30000/fs/
查看文件列表 - 通过 postman 上传文件
curl --location --request POST 'k8s-master:30000/upload' \
--form 'datafile=@"/I:/workspace/k8s/kube-dns-svc.yml"'
- 再次查看浏览器地址文件列表,查看 container 资源内文件列表及 pv 对应目录的文件列表(创建 pv 时有指定
/data/k8s
) -
kubectl delete deployment fs-deployment
删除服务资源或进行更新等操作,查看 pv 对应资源是否持久化(是,成功)
其他技巧
限制重启后 deployment 资源的数量
如上文中下图是因为重复了多次 kubectl apply
资源操作,导致遗留了很多无用的资源信息。
可以通过 deployment.spec.revisionHistoryLimit
来进行限制:
➜ ~ kubectl explain deployment.spec.revisionHistoryLimit
FIELD: revisionHistoryLimit <integer>
DESCRIPTION:
The number of old ReplicaSets to retain to allow rollback. This is a
pointer to distinguish between explicit zero and not specified.
shell 操作没有提示
参考 k8s命令自动补全(只是 bash 使用的,在 zsh 或者说 Oh-my-zsh 上不好用)
kubectl api-resources
kubectl api-resources
可以显示所有 k8s 资源,但目前由于集群版本问题不显示。后面再了解。
网友评论