在我的上一篇文章Understanding Unix Domain Sockets in Golang中,我提到了Unix域插座的一个潜在用例是在Kubernetes中的容器之间进行通信。我收到了有关如何执行此操作的示例的请求,因此在这篇文章中,我将使用两个GO应用程序提供一个简单的示例,您可以在此repository中找到。
使用Kubernetes中的Unix域插座可以是在同一豆荚内传达容器的有效方法。
使用UNIX域插座进行K8S中的POD中的容器之间进行通信的一些优势是:
- 通信比使用网络插座更快。当容器需要经常通信或传输大量数据时,这可能很有用。
- 不需要网络接口
- 安全传输,通信仅限于本地主机。
- 简单性,不需要IP地址或端口号。好的,这也许不是一个很大的优势,但是Yolo!
在K8S中,您可以通过在容器之间共享卷并将卷中的套接字作为通信通道中的插座文件来实现。
在Kubernetes中分享数量:
要在同一POD中的两个容器之间共享UNIX域套接字文件,您必须创建一个emptyDir
卷并将其安装在两个容器中。在Kubernetes中,您可以在YAML中的容器规范中使用volumeMount
进行此操作。
当POD分配给节点并存在只要POD在该节点上运行时,
空dir卷是创建的临时卷。使用一个空目录初始化了一个空dir卷,可用于存储POD中的容器之间共享的数据。
这是您如何创建卷并将其安装在两个容器中的示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: kungfudev-deploy
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: nethttp
image: douglasmakey/simple-http:latest
volumeMounts:
- mountPath: /tmp/
name: socket-volume
- name: unixhttp
image: douglasmakey/simple-http-uds:latest
volumeMounts:
- mountPath: /tmp/
name: socket-volume
volumes:
- name: socket-volume
emptyDir: {}
在此示例中,nethttp
和unixhttp
都在/tmp
中的容器文件系统中安装了一个卷,该卷使他们可以访问卷中的相同文件。
跑步
准备在自己的kubernetes群集中尝试一下吗?查看此repository,它具有您需要入门的一切!存储库中随附的Earthfile
将帮助您构建和创建容器映像以在本地K8S群集中使用,或者您可以简单地使用Docker Hub上发布的图像。请按照上面的示例YAML设置您自己的UNIX域插座在容器之间进行通信。
尘世是使用容器构建,测试和部署应用程序的工具。它提供了一个易于使用的命令行界面,用于使用称为EarthFile的脚本定义和自动化项目的构建,测试和部署步骤。
一旦部署在您的K8S群集上启动并运行,就该将其进行测试了!前往nethttp
容器,并使用卷发向/test
提出请求以查看其性能。
$ k exec -it kungfudev-deploy -c nethttp bash
---
$ curl localhost:8000/test
Hello kung fu developer from a server running on UDS!
告诉我代码!
unixhttp
应用程序代码:
package main
import (...)
const socketPath = "/tmp/httpecho.sock"
func main() {
// Create a Unix domain socket and listen for incoming connections.
socket, err := net.Listen("unix", socketPath)
if err != nil {
log.Fatal(err)
}
// Cleanup the sockfile.
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
os.Remove(socketPath)
os.Exit(1)
}()
m := http.NewServeMux()
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hi kung fu developer from a server running on UDS! \n"))
})
server := http.Server{Handler: m}
if err := server.Serve(socket); err != nil {
log.Fatal(err)
}
}
nethttp
应用程序代码:
package main
import (...)
var (
socketPath = "/tmp/httpecho.sock"
// Creating a new HTTP client that is configured to make HTTP requests over a Unix domain socket.
httpClient = http.Client{
Transport: &http.Transport{
// Set the DialContext field to a function that creates
// a new network connection to a Unix domain socket
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", socketPath)
},
},
}
)
func test(w http.ResponseWriter, req *http.Request) {
resp, err := httpClient.Get("http://unix/")
if err != nil {
http.Error(w, err.Error(), 500)
}
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err != nil {
http.Error(w, err.Error(), 500)
}
w.Write(b)
}
func main() {
http.HandleFunc("/test", test)
if err := http.ListenAndServe(":8000", nil); err != nil {
log.Fatal(err)
}
}
就是这样!只需几个简单的步骤,您就可以利用Unix域插座的功率在Kubernetes Pod中的容器之间进行通信。这可能是一个简单的例子,但是该技术可以应用于各种现实世界的情况。感谢您的关注,希望您发现此示例有帮助且易于理解。愉快的编码!