I am trying to run a very simple UDP service in kubernetes on Google Cloud but am unable to access the port I am exposing to the internet. Here is the deployment and service file:
Deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: udp-server-deployment
spec:
replicas: 2
template:
metadata:
labels:
name: udp-server
spec:
containers:
- name: udp-server
image: jpoon/udp-server
imagePullPolicy: Always
ports:
- containerPort: 10001
protocol: UDP
Service.yaml:
apiVersion: v1
kind: Service
metadata:
name: udp-server-service
labels:
app: udp-server
spec:
type: LoadBalancer
ports:
- port: 10001
protocol: UDP
selector:
name: udp-server
This creates the loadbalancer in Google Cloud with the correct port exposed. Like so:
But when i try to access the port it's unaccessible. I have tried a few variations in GCE to expose udp port but none seem to be working.
➜ udp-example telnet 35.192.59.72 10001
Trying 35.192.59.72...
telnet: connect to address 35.192.59.72: Connection refused
telnet: Unable to connect to remote host
I tried to replicate this issue and I believe it is caused by the kubernetes configuration that is failing but how you are trying test it and possibly a missing firewall rule.
First of all consider that opening a connection to the target host:port
using telnet
will always fail because the protocol you are using is UDP and not TCP, therefore no connection will be created even if the server is up and running. And remember to create the corresponding firewall rule to be sure that the traffic is allowed.
I went to check the source image of the go server and of the go client, I took their go
source code and they are working on localhost, but they are not running the client on a different instance and targeting the loadbalancer.
Therefore to understand if it was kubernetes failing I tried to make use to the very same yaml file with the nginx image and TCP and everything works.
In the very same GitHub page there is the example of the Dockerfile of the server that contains this line:
# Expose your port
EXPOSE 61243
Therefore I have ssh into the container (note ash
and not bash
) in order to understand what is actually going on and on which port the server it is listening and which port is exposed by Docker.
kubectl exec -it udp-server-deployment-8306694-zq412 -- /bin/ash
However keep in mind that:
The EXPOSE instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published.
Once I was inside the container I have run the client with the following output both targeting local host and the loadbalancer IP:
/go/src/udp # go run client.go
SERVER_ADDRESS=
ServerAddr=:10001
Received udp-server-deployment-8306694-zq412 from 127.0.0.1:10001
Mening that the server was correctly working.
Connecting with the client from Cloud Shell was not working since the firewall rules do not applies there (my mistake).
To test it is correctly working spin up an instance, install go, run the client and check that it is working.
curl -O https://storage.googleapis.com/golang/go1.7.4.linux-amd64.tar.gz
tar xvf go1.7.4.linux-amd64.tar.gz
sudo chown -R root:root ./go
sudo mv go /usr/local
vi client.go
/usr/local/go/bin/go run client.go
where this is the content of client.go:
package main
import (
"fmt"
"net"
"strconv"
"time"
)
func checkError(err error) {
if err != nil {
fmt.Println("Error: ", err)
}
}
func main() {
Server := "[LOAD BALANCER IP]"
fmt.Println("SERVER_ADDRESS=" + Server)
serverAddr, err := net.ResolveUDPAddr("udp", Server+":10001")
fmt.Println("ServerAddr=" + serverAddr.String())
checkError(err)
conn, err := net.DialUDP("udp", nil, serverAddr)
checkError(err)
defer conn.Close()
buf := make([]byte, 1024)
i := 0
for {
msg := strconv.Itoa(i)
fmt.Fprintf(conn, msg)
i++
n, addr, err := conn.ReadFromUDP(buf)
fmt.Println("Received ", string(buf[0:n]), " from ", addr)
if err != nil {
fmt.Println("Error: ", err)
}
time.Sleep(time.Second * 1)
}
}
Note that you have to replace the [LOAD BALANCER IP]
placeolder with your value.