python websocket client and with auth header

# import asyncio
import ssl
from socket import socket

import websocket
# import websockets

def on_message(ws, message):
    print ('message received ..')
    print (message)


def on_error(ws, error):
    print ('error happened .. ')
    print (error)


def on_close(ws):
    print ("### closed ###")


def on_open(ws):

    print ('Opening Websocket connection to the server ... ')

    ## This session_key I got, need to be passed over websocket header isntad of ws.send.
    ws.send("testing message here")

websocket.enableTrace(True)

token = "........"
auth = "Authorization: Bearer " + token
ws = websocket.WebSocketApp("wss://APISERVER:8443/api/v1/namespaces/default/services/the-service:8889/proxy/websocket?token=123",
                            on_open = on_open,
                            on_message = on_message,
                            on_error = on_error,
                            on_close = on_close,
                            header = [auth]
                            )

ws.on_open = on_open

##Note: this is for --insecure flag in curl, basically to tell the client not verify the ssl certificate
ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
# socket.setsockopt

get those APIServer and token using

APISERVER=$(kubectl config view --minify | grep server | cut -f 2- -d ":" | tr -d " ")
SECRET_NAME=$(kubectl get secrets | grep ^default | cut -f1 -d ' ')
TOKEN=$(kubectl describe secret $SECRET_NAME | grep -E '^token' | cut -f2 -d':' | tr -d " ")

curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure

Start a websocket server with tornado

import tornado.ioloop
import tornado.web
import tornado.escape
import tornado.ioloop
import tornado.web
import tornado.websocket
import tornado.options
import time
import logging
import uuid
import sys,os
from tornado.options import define, options



class MainHandler(tornado.web.RequestHandler):
	def get(self):
		self.write("Hello, world")

def make_app():
	return tornado.web.Application([
		(r"/", MainHandler),
	])



define('port', default=8889, help="The tornado server port", type=int)


class WebSocketSever(tornado.websocket.WebSocketHandler):
	bao_cons = set()
	bao_waiters = {}
	global con_key
	global token

	# def initialize(self, my_object):
	# 	self.my_object = my_object

	def open(self):
		sole_id = str(uuid.uuid4()).upper()
		print(sole_id)
		self.con_key = sole_id
		self.token = self.get_argument("token")
		self.bao_waiters["{}".format(sole_id)] = self
		self.bao_cons.add(self)
		# self.write_message({"websocket_sole_id": sole_id})
		self.write_message({"token": self.token})
		logging.info("websocket opened!")
		print(self.bao_cons)

	def on_message(self, message):

		print(type(message))
		if message == "close":
			self.close()
			return
		try:
			parse_data = tornado.escape.json_decode(message)
			if parse_data["user"] and parse_data["content"]:
				user = parse_data["user"]
				content = parse_data["content"]
				if not user or not content:
					logging.info("Date is wrong!")
					return
				else:
					for key in self.bao_waiters.keys():
						if key == user:
							try:
								self.bao_waiters[key].write_message("{}".format(content))
							except Exception as e:
								logging.info(e)
							finally:
								logging.info("process finished!")
		except:
			for con in self.bao_cons:
				con.write_message(message)

	def check_origin(self, origin: str):
		return True

	def allow_draft76(self):
		return True

	def on_close(self):
		self.bao_cons.remove(self)
		# self.bao_waiters.pop(self.con_key)
		self.bao_waiters.pop(self.token)

		logging.info("websocket closed!")
		print(self.bao_cons)


class Application(tornado.web.Application):
	def __init__(self, handlers, setting):
		super(Application, self).__init__(handlers, **setting)


def main():
	options.parse_command_line()
	handlers = [
		(r"/websocket", WebSocketSever),
		(r"/http", MainHandler),
	            ]
	setting = dict(xsrf_cookies=False)
	app = Application(handlers, setting)
	print(options.port)

	app.listen(options.port)
	tornado.ioloop.IOLoop.current().start()


if __name__ == "__main__":
	# app = make_app()
	# app.listen(8889)
	# tornado.ioloop.IOLoop.current().start()
	main()

then to access the websocket server, for example, using javascript

var ws = new WebSocket("ws://127.0.0.1:8080/api/v1/namespaces/default/services/serices:8889/proxy/websocket?token=123");
ws.onopen = function() {
   ws.send("Hello, world");
};
ws.onmessage = function (evt) {
   alert(evt.data);
};

Expose existing deployment

expose the deployment, pod, or replicateset using the expose command

kubectl expose replicasets.apps existing-rc –port=9000 –target-port=9000 –type=NodePort –name=testport

otherwise, if you already have a service running, you can upgrade it

`kubectl patch svc existing-service -p ‘{“spec”: {“type”: “NodePort”}}’`

Note, if you already have cluster IP, you can also use LoadBalancer.

after that, you should have the service with the necessary port information

Screenshot 2020-03-18 at 12.11.36 PM

if you are using minikube locally, you can get the URL as:

minikube service –url the-new-service

Screenshot 2020-03-18 at 12.13.25 PM

alternatively, you could also achive this by port forward

kubectl port-forward svc/existing-service host-port:container-port

as such, the service could be reached at hostname:host-port, for example: 127.0.0.1:host-port

expose more ports for existing service

(base) ➜ ~ kubectl get service local-files-12a341c023 -o yaml



then patch accoring to the spec:

kubectl patch services local-files-12a341c023 --type='json' -p='[{"op": "add", "path": "/spec/ports/-", "value": {"name":"tornado","port":8889,"targetPort": 8889,"protocol":"TCP"}}]'

expose Kubernetes cluster service

expose the deployment, pod, or replicateset using the expose command

kubectl expose replicasets.apps existing-rc –port=9000 –target-port=9000 –type=NodePort –name=testport

otherwise, if you already have a service running, you can upgrade it

`kubectl patch svc existing-service -p ‘{“spec”: {“type”: “NodePort”}}’`

 

Note, if you already have cluster IP, you can also use LoadBalancer.

after that, you should have the service with the necessary port information

Screenshot 2020-03-18 at 12.11.36 PM

if you are using minikube locally, you can get the URL as:

minikube service –url the-new-service

Screenshot 2020-03-18 at 12.13.25 PM

docker container to talk to Kubernetes Cluster

There could be need to talk to Kubernetest cluster from segregated docker containers. It’s possible to do so:

 

 

build the pipe from the container to the host machine

There are several ways to connect the host machine. the container is running together with the host, behaving like on the same subnet. you can access it through the public IP.

otherwise, more elegantly, you can leverage on host.docker.internal to talk to the host

 

proxy the resources for the Kubernetes cluster

you can start a Kubernetest proxy to talk to the cluster.

kubectl proxy --port=8080 --disable-filter &

 

 

then to talk to the resources in the cluster from the container, you can do

host.docker.internal:8080/api/v1/namespaces/default/services/pod:{port}/proxy/

 

Kubernetes service vs deployment

Kubernetes Service vs Deployment

What’s the difference between a Service and a Deployment in Kubernetes?

A deployment is responsible for keeping a set of pods running.

A service is responsible for enabling network access to a set of pods.

We could use a deployment without a service to keep a set of identical pods running in the Kubernetes cluster. The deployment could be scaled up and down and pods could be replicated. Each pod could be accessed individually via direct network requests (rather than abstracting them behind a service), but keeping track of this for a lot of pods is difficult.

We could also use a service without a deployment. We’d need to create each pod individually (rather than “all-at-once” like a deployment). Then our service could route network requests to those pods via selecting them based on their labels.

Services and Deployments are different, but they work together nicely.

 

source: https://matthewpalmer.net/kubernetes-app-developer/articles/service-kubernetes-example-tutorial.html