Commit 376680b5 authored by Santhosh's avatar Santhosh

initial commit

parents
Pipeline #1953 failed with stages
File added
23d0369:e71c7948d79d6bd48183dc650ff56b7a
FROM python:3.8-slim
# Install any dependencies your function may have
# For example, if you're using Flask:
# RUN pip install flask
# Copy your function code into the container
COPY hello.py /home/app/
# Set working directory
WORKDIR /home/app/
# Define the command to run your function
CMD ["python", "hello.py"]
service: hello
provider:
name: kubeless
runtime: python3.9
plugins:
- serverless-kubeless
functions:
hello:
description: 'Hello function'
handler: handler.hello
kubectl create secret generic regcred --from-file=.dockerconfigjson=faas/config.json --type=kubernetes.io/dockerconfigjson
kubectl config view --minify --raw > kube_config
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "bXNhbnRoOmRja3JfcGF0XzZJcmpxNTdhazk1Q3I1R054YkZwZTlDeFFGYw=="
}
}
}
\ No newline at end of file
#!pip install kubernetes
from kubernetes import client, config
import time
class FunctionController:
def __init__(self):
# Load Kubernetes configuration
config.load_kube_config()
# Initialize Kubernetes API client
self.k8s_client = client.CoreV1Api()
def create_function(self, function_name, image, replicas=1):
# Define function deployment object
deployment = client.V1Deployment()
deployment.metadata = client.V1ObjectMeta(name=function_name)
deployment.spec = client.V1DeploymentSpec(
replicas=replicas,
selector=client.V1LabelSelector(
match_labels={"app": function_name}
),
template=client.V1PodTemplateSpec(
metadata=client.V1ObjectMeta(labels={"app": function_name}),
spec=client.V1PodSpec(
containers=[client.V1Container(
name=function_name,
image=image,
ports=[client.V1ContainerPort(container_port=8080)]
)]
)
)
)
# Create function deployment
self.k8s_client.create_namespaced_deployment(namespace='default', body=deployment)
def scale_function(self, function_name, replicas):
# Get function deployment
deployment = self.k8s_client.read_namespaced_deployment(name=function_name, namespace='default')
# Update replicas
deployment.spec.replicas = replicas
# Apply changes
self.k8s_client.patch_namespaced_deployment(name=function_name, namespace='default', body=deployment)
if __name__ == "__main__":
controller = FunctionController()
# Example: Create a function
controller.create_function(function_name="hello-python", image="your-registry/hello-python:latest")
# Example: Scale a function
controller.scale_function(function_name="hello-python", replicas=3)
# Keep the controller running
while True:
time.sleep(60) # Sleep to prevent high CPU usage
FROM python:3.9-slim
# Set the working directory in the container
WORKDIR /app
# Copy the function code into the container
COPY function.py .
# Install any dependencies
RUN pip install requests
# Define the command to run the function
CMD ["python", "function.py"]
def main(request):
"""
Entry point of the function.
"""
if request is not None and 'name' in request:
name = request['name']
return f"Hello, {name}!"
else:
return "Hello, World!"
from flask import Flask, request, jsonify
from kubernetes import client, config, watch
import threading
# Load Kubernetes configuration from default location
config.load_kube_config()
# Define Kubernetes API client
k8s_client = client.ApiClient()
# Define custom resource group/version
group = 'example.com'
version = 'v1'
# Define custom resource plural
plural = 'functions'
# Define custom resource API
crd_api = client.CustomObjectsApi(k8s_client)
# Define namespace where functions will be deployed
namespace = 'default'
# Initialize Flask app
app = Flask(__name__)
# Dictionary to store function replicas
function_replicas = {}
def deploy_function(function_name, image):
"""
Deploy a function to Kubernetes as a custom resource.
"""
# Define function resource
function_resource = {
'apiVersion': f'{group}/{version}',
'kind': 'Function',
'metadata': {'name': function_name},
'spec': {'image': image}
}
# Create function resource in Kubernetes
k8s_client.create_namespaced_custom_object(group, version, namespace, plural, function_resource)
print(f"Function {function_name} deployed with image {image}.")
def update_function(function_name, image):
"""
Update an existing function in Kubernetes.
"""
# Define function resource
function_resource = {
'apiVersion': f'{group}/{version}',
'kind': 'Function',
'metadata': {'name': function_name},
'spec': {'image': image}
}
# Update function resource in Kubernetes
k8s_client.replace_namespaced_custom_object(group, version, namespace, plural, function_name, function_resource)
print(f"Function {function_name} updated with image {image}.")
def scale_function(function_name, replicas):
"""
Scale the number of replicas for a function in Kubernetes.
"""
# Define function scale spec
scale_spec = {'spec': {'replicas': replicas}}
# Patch function scale in Kubernetes
k8s_client.patch_namespaced_custom_object_scale(group, version, namespace, plural, function_name, scale_spec)
print(f"Function {function_name} scaled to {replicas} replicas.")
def handle_function(event):
"""
Handle function events (create, update, delete).
"""
function = event['object']
function_name = function['metadata']['name']
function_status = event['type']
if function_status == 'ADDED':
print(f"Function {function_name} added.")
deploy_function(function_name, function['spec']['image'])
elif function_status == 'MODIFIED':
print(f"Function {function_name} modified.")
update_function(function_name, function['spec']['image'])
elif function_status == 'DELETED':
print(f"Function {function_name} deleted.")
def watch_functions():
"""
Watch for changes to function resources.
"""
resource_version = ''
while True:
stream = watch.Watch().stream(crd_api.list_namespaced_custom_object, group, version, namespace, plural, resource_version=resource_version)
for event in stream:
resource_version = event['object']['metadata']['resourceVersion']
handle_function(event)
def auto_scale():
"""
Auto-scale functions based on request rate.
"""
while True:
# Example auto-scaling logic
for function_name in function_replicas:
# Adjust number of replicas based on request rate
request_rate = function_replicas.get(function_name, 0)
replicas = min(max(int(request_rate / 10), 1), 10) # Scale between 1 and 10 replicas
scale_function(function_name, replicas)
# Sleep for 1 minute (adjust as needed)
time.sleep(60)
@app.route('/invoke', methods=['POST'])
def invoke_function():
"""
Handle HTTP POST requests to invoke functions.
"""
data = request.get_json()
function_name = data.get('function_name')
# Increment request rate for function
function_replicas[function_name] = function_replicas.get(function_name, 0) + 1
return jsonify({'message': f"Function {function_name} invoked."})
if __name__ == '__main__':
# Start watching for changes to function resources
watch_thread = threading.Thread(target=watch_functions, daemon=True)
watch_thread.start()
# Start auto-scaling thread
auto_scale_thread = threading.Thread(target=auto_scale, daemon=True)
auto_scale_thread.start()
# Run Flask app
app.run(host='0.0.0.0', port=5000)
import os
import subprocess
import yaml
from kubernetes import client, config
# Load Kubernetes configuration from default location
config.load_kube_config()
# Kubernetes API client
k8s_client = client.ApiClient()
# Docker Hub username (replace with your Docker Hub username)
docker_username = "msanth"
def build_and_push_image(function_name):
"""
Build the Docker image and push it to Docker Hub.
"""
# Change directory to function directory
os.chdir(function_name)
# Build Docker image
subprocess.run(["docker", "build", "-t", f"{docker_username}/{function_name}:latest", "."], check=True)
# Push Docker image to Docker Hub
subprocess.run(["docker", "push", f"{docker_username}/{function_name}:latest"], check=True)
# Change back to original directory
os.chdir("..")
def create_deployment(function_name):
"""
Create a Kubernetes Deployment resource for the function.
"""
deployment_manifest = {
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {"name": function_name},
"spec": {
"replicas": 1,
"selector": {"matchLabels": {"app": function_name}},
"template": {
"metadata": {"labels": {"app": function_name}},
"spec": {
"containers": [{
"name": function_name,
"image": f"{docker_username}/{function_name}:latest",
"ports": [{"containerPort": 8080}] # Assuming function listens on port 8080
}]
}
}
}
}
#yourusername Create Deployment in Kubernetes
api_instance = client.AppsV1Api(k8s_client)
api_instance.create_namespaced_deployment(namespace="default", body=deployment_manifest)
print(f"Deployment created for {function_name}.")
def create_service(function_name):
"""
Create a Kubernetes Service resource for the function.
"""
service_manifest = {
"apiVersion": "v1",
"kind": "Service",
"metadata": {"name": f"{function_name}-service"},
"spec": {
"selector": {"app": function_name},
"ports": [{"protocol": "TCP", "port": 8080, "targetPort": 8080}], # Assuming function listens on port 8080
"type": "ClusterIP" # Expose service only within the cluster
}
}
# Create Service in Kubernetes
#k8s_client.create_namespaced_service(namespace="default", body=service_manifest)
api_instance = client.CoreV1Api()
api_instance.create_namespaced_service(namespace="default", body=service_manifest)
print(f"Service created for {function_name}.")
def deploy_function(function_name):
"""
Deploy the function to Kubernetes.
"""
build_and_push_image(function_name)
create_deployment(function_name)
create_service(function_name)
if __name__ == "__main__":
function_name = input("Enter the name of the function directory: ")
deploy_function(function_name)
apiVersion: apps/v1
kind: Deployment
metadata:
name: function-deployment
spec:
replicas: 1
selector:
matchLabels:
app: function
template:
metadata:
labels:
app: function
spec:
containers:
- name: function
image: yourusername/function-name:latest
ports:
- containerPort: 8080 # Assuming your function listens on port 8080
apiVersion: v1
kind: Service
metadata:
name: function-service
spec:
selector:
app: function
ports:
- protocol: TCP
port: 8080 # Port on which your function container is listening
targetPort: 8080 # Port to forward traffic to in the pod
type: ClusterIP # Expose service only within the cluster
from flask import Flask, request, jsonify
from kubernetes import client, config, watch
from prometheus_client import Counter, Gauge, generate_latest, CONTENT_TYPE_LATEST
from prometheus_client.exposition import make_wsgi_app
from werkzeug.middleware.dispatcher import DispatcherMiddleware
import threading
import time
import requests
from wsgiref.simple_server import make_server
# Load Kubernetes configuration from default location
config.load_kube_config()
# Define Kubernetes API client
k8s_client = client.ApiClient()
# Initialize Flask app
app = Flask(__name__)
# Prometheus metrics
function_invocation_counter = Counter('function_invocation_count', 'Number of function invocations', ['function_name'])
function_request_rate_gauge = Gauge('function_request_rate', 'Request rate for functions', ['function_name'])
def deploy_function(function_name, image):
"""
Deploy a function to Kubernetes as a Deployment.
"""
# Define deployment spec
deployment_spec = {
'apiVersion': 'apps/v1',
'kind': 'Deployment',
'metadata': {'name': function_name},
'spec': {
'replicas': 1,
'selector': {'matchLabels': {'app': function_name}},
'template': {
'metadata': {'labels': {'app': function_name}},
'spec': {
'containers': [{
'name': function_name,
'image': image,
'ports': [{'containerPort': 8080}]
}]
}
}
}
}
# Create deployment in Kubernetes
api_instance = client.AppsV1Api(k8s_client)
api_instance.create_namespaced_deployment(namespace='default', body=deployment_spec)
print(f"Function {function_name} deployed with image {image}.")
def scale_function(function_name, replicas):
"""
Scale the number of replicas for a function in Kubernetes.
"""
# Define HPA spec
hpa_spec = {
'apiVersion': 'autoscaling/v1',
'kind': 'HorizontalPodAutoscaler',
'metadata': {'name': f'{function_name}-hpa'},
'spec': {
'scaleTargetRef': {
'apiVersion': 'apps/v1',
'kind': 'Deployment',
'name': function_name
},
'minReplicas': 1,
'maxReplicas': replicas,
'targetCPUUtilizationPercentage': 50 # Adjust as needed
}
}
# Create HPA in Kubernetes
api_instance = client.CoreV1Api()
k8s_client.create_namespaced_horizontal_pod_autoscaler(namespace='default', body=hpa_spec)
print(f"Function {function_name} auto-scaler created with max replicas {replicas}.")
def handle_function(event):
"""
Handle function events (create, update, delete).
"""
function = event['object']
function_name = function['metadata']['name']
function_status = event['type']
if function_status == 'ADDED':
print(f"Function {function_name} added.")
deploy_function(function_name, function['spec']['image'])
scale_function(function_name, 10) # Initially scale to max replicas of 10
elif function_status == 'MODIFIED':
print(f"Function {function_name} modified.")
# For simplicity, we don't handle updates in this example
elif function_status == 'DELETED':
print(f"Function {function_name} deleted.")
def watch_functions():
"""
Watch for changes to function resources.
"""
resource_version = ''
v1 = client.CoreV1Api()
w = watch.Watch()
while True:
stream = w.stream(v1.list_namespaced_custom_object, group='example.com', version='v1', namespace='default', plural='functions', resource_version=resource_version)
for event in stream:
resource_version = event['object']['metadata']['resourceVersion']
handle_function(event)
@app.route('/invoke', methods=['POST'])
def invoke_function():
"""
Handle HTTP POST requests to invoke functions.
"""
data = request.get_json()
function_name = data.get('function_name')
# Increment request rate for function
function_request_rate_gauge.labels(function_name=function_name).inc()
# Increment invocation count for function
function_invocation_counter.labels(function_name=function_name).inc()
# Invoke function
result = invoke_kubernetes_function(function_name)
return jsonify({'message': f"Function {function_name} invoked. Result: {result}"})
def invoke_kubernetes_function(function_name):
"""
Invoke a Kubernetes function by sending an HTTP request.
"""
# Assuming the function is exposed via a service with type ClusterIP
# You need to replace 'function-service' with the actual service name in your Kubernetes cluster
url = f"http://function-service.default.svc.cluster.local:8080/invoke"
# Example payload, adjust as needed
payload = {
"message": "Hello from Python!"
}
try:
response = requests.post(url, json=payload)
if response.status_code == 200:
return response.json() # Assuming the function returns JSON response
else:
return f"Error: {response.status_code}"
except requests.exceptions.RequestException as e:
return f"Error: {e}"
def metrics_app(environ, start_response):
"""
Serve Prometheus metrics.
"""
response_body = generate_latest()
status = '200 OK'
headers = [('Content-type', CONTENT_TYPE_LATEST)]
start_response(status, headers)
return [response_body]
if __name__ == '__main__':
# Start watching for changes to function resources
watch_thread = threading.Thread(target=watch_functions, daemon=True)
watch_thread.start()
# Run Flask app
app.run(host='0.0.0.0', port=5000)
# Serve Prometheus metrics
metrics_app_wrapper = DispatcherMiddleware(app.wsgi_app, {'/metrics': metrics_app})
httpd = make_server('0.0.0.0', 8080, metrics_app_wrapper)
httpd.serve_forever()
# hello.py
def handle(req):
return "Hello, World!"
apiVersion: batch/v1
kind: Job
metadata:
name: hello-1
spec:
template:
# This is the pod template
spec:
containers:
- name: hello
image: busybox:1.28
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
imagePullSecrets:
- name: regcred
# The pod template ends here
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: ui-acct
namespace: kubeless
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: kubeless-ui
rules:
- apiGroups:
- ""
resources:
- pods
- pods/log
verbs:
- get
- list
- apiGroups:
- kubeless.io
resources:
- functions
verbs:
- get
- list
- watch
- update
- create
- delete
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- proxy
- apiGroups:
- ""
resources:
- services/proxy
verbs:
- get
# the 'create' verb is required because otherwise POST requests are blocked
- create
- proxy
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: kubeless-ui
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubeless-ui
subjects:
- kind: ServiceAccount
name: ui-acct
namespace: kubeless
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
controller: ui
namespace: kubeless
name: ui
spec:
replicas: 1
selector:
matchLabels:
controller: ui
template:
metadata:
labels:
controller: ui
spec:
containers:
- name: ui
image: bitnami/kubeless-ui:latest
imagePullPolicy: Always
ports:
- containerPort: 3000
protocol: TCP
- name: proxy
image: lachlanevenson/k8s-kubectl:v1.13.1
imagePullPolicy: Always
args:
- proxy
- "-p"
- "8080"
serviceAccountName: ui-acct
---
apiVersion: v1
kind: Service
metadata:
labels:
controller: ui
name: ui