上一部分与大家分享到 Statefulset 与 RplicaSet 的区别,以及 Statefulset 的特点,能做的一些事情及一些注意事项
现在我们来尝试使用 Statefulset 来部署我们的应用,我们可以需要有应用程序,然后有持久化卷
开始使用 Statefulset 部署应用
Statefulset 部署应用,我们需要完成这些资源的创建:
- 制作应用程序和镜像
- 编写 Service
- 编写 Statefulset 指定 pod 模板及挂载
制作应用程序和镜像
编写应用程序
此处我们可以制作一个应用程序,会写数据到磁盘的某个路径下面,现在就用 golang 来简单写一个 http 服务器
- 监听 8080 端口
- 提供 GET 和 POST 请求
- 收到 GET 请求的时候,读取 /var/data/stateful.txt 中的内容
- 收到 POST 请求的时候,会将请求的内容写入到 /var/data/stateful.txt 文件中
文件目录是这样的
main.go 可以分为这几个部分
- http 服务器部分
const (
filePath = "/var/data/stateful.txt"
fileDir = "/var/data"
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
str, err := readFileContent(filePath)
if err != nil {
fmt.Println(" readFileContent err : ", err)
return
}
//输出json结果给调用方
c.JSON(200, gin.H{
"message": str,
})
})
r.POST("/", func(c *gin.Context) {
buf := make([]byte, 1024)
n, _ := c.Request.Body.Read(buf)
fmt.Println(string(buf[0:n]))
err := writeFileContent(filePath, buf[0:n])
if err != nil {
fmt.Println(" writeFileContent err : ", err)
return
}
//输出json结果给调用方
c.JSON(http.StatusOK, gin.H{
"message": string(buf[0:n]),
})
})
r.Run(":8080")
}
使用了 golang 中的 gin 框架,提供一个 GET 和 一个 POST 方法,GET 方法用于读取文件内容,POST 方法用于写入文件内容
- 写文件部分
func processFileErr(err error, file string) (*os.File, error) {
var f *os.File
if os.IsNotExist(err) {
gErr := os.MkdirAll(fileDir, 0775)
if gErr != nil {
fmt.Println("MkdirAll file error : ", gErr)
return nil, gErr
}
f, gErr = os.Create(file)
if gErr != nil {
fmt.Println("Create file error : ", gErr)
return nil, gErr
}
} else {
fmt.Println("OpenFile file error : ", err)
return nil, err
}
return f, nil
}
func writeFileContent(file string, content []byte) error {
f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775)
if err != nil {
var pErr error
f, pErr = processFileErr(err, file)
if pErr != nil {
fmt.Println("processFileErr error : ", pErr)
return pErr
}
}
defer f.Close()
fmt.Println("Write content : ", string(content))
_, err = f.Write(content)
if err != nil {
fmt.Println("Write file error : ", err)
return err
}
return nil
}
writeFileContent 方法主要是用来写入数据到文件中
processFileErr 会处理文件不存在的错误信息,同时会创建不存在的路径和文件,并返回创建文件的文件指针
- 读取文件信息部分
func readFileContent(file string) (string, error) {
f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE, 0775)
if err != nil {
var pErr error
f, pErr = processFileErr(err, file)
if pErr != nil {
fmt.Println("processFileErr error : ", pErr)
return "", pErr
}
}
defer f.Close()
buf := make([]byte, 1024)
n, err := f.Read(buf)
if err == io.EOF {
return "", nil
}
if err != nil {
fmt.Println("Read file error : ", err)
}
fmt.Println("read content : ", string(buf))
return string(buf[0:n]), nil
}
读取文件部分,同样需要使用 processFileErr 处理文件不存在的错误信息,主要是从传入的文件中读取文件内容,以字符串的形式作为函数返回值
制作镜像
Dockerfile:
将 myhttp 可执行程序加入到镜像中
FROM node:7
ADD myhttp /myhttp
ENTRYPOINT ["./myhttp"]
执行如下指令制作镜像:
看到这里的兄弟,请将镜像传到你自己的账号下面,记得登录哦
docker build -t xiaomotong888/sta-kubia .
docker push xiaomotong888/sta-kubia
上传镜像之后,我们可以通过 docker search 账号名 来查看自己的镜像列表,看到如下内容,说明可以往下继续完成其他步骤了
编写 Service
接下来便是编写 Service 部分的清单了,我们在玩 Statefulset 管理 pod 的时候,咱们创建的是有状态的 pod,咱们还需要创建一个 headless Service 来给 pod 之间提供网络标识
例如,我们可以这样来创建
sta-service.yaml
apiVersion: v1
kind: Service
metadata:
name: sta-kubia
spec:
clusterIP: None
selector:
app: sta-kubia
ports:
- name: http
port: 80
创建的一个 Service
- 名称为 sta-kubia
- 选择的 pod 标签是 sta-kubia
- svc 集群内部的端口是 80
这里需要注意的是,我们之前写 Service 清单的时候,如果不指定 type,那么 Service 默认是 clusterIP,但是现在我们是连 clusterIP 都不想要,我们需要将 clusterIP 置为 None
通过 kubectl create -f sta-service.yaml 创建一个 Service ,可以看到 CLUSTER-IP 一栏为 None 即为正确创建好 Service
curl localhost:8001/api/v1/namespaces/default/pods/sta-kubia-0/proxy/
curl -X POST -d 'helloworld sta-kubia-0' localhost:8001/api/v1/namespaces/default/pods/sta-kubia-0/proxy/
今天就到这里,学习所得,若有偏差,还请斧正
欢迎点赞,关注,收藏
朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力
好了,本次就到这里
技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
我是阿兵云原生,欢迎点赞关注收藏,下次见~
更多的可以查看 零声每晚八点直播:https://ke.qq.com/course/417774