diff --git a/docs/kubernetes-production/functions-config.yaml b/docs/kubernetes-production/functions-config.yaml new file mode 100644 index 000000000..030185f99 --- /dev/null +++ b/docs/kubernetes-production/functions-config.yaml @@ -0,0 +1,7 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: functions-config +data: + MQ: redis://redis-master.default + DB: postgres://postgres:mysecretpassword@postgresql-master.default/?sslmode=disable \ No newline at end of file diff --git a/docs/kubernetes-production/functions-deployment.yaml b/docs/kubernetes-production/functions-deployment.yaml new file mode 100644 index 000000000..c6d9c79fa --- /dev/null +++ b/docs/kubernetes-production/functions-deployment.yaml @@ -0,0 +1,43 @@ +--- +kind: Deployment +apiVersion: extensions/v1beta1 +metadata: + name: functions + labels: + app: functions +spec: + replicas: 1 + template: + metadata: + labels: + app: functions + spec: + containers: + - name: functions + image: iron/functions + securityContext: + privileged: true + env: + - name: DOCKER_HOST + value: unix:///var/run/docker.sock + - name: MQ + valueFrom: + configMapKeyRef: + name: functions-config + key: MQ + - name: DB + valueFrom: + configMapKeyRef: + name: functions-config + key: DB + volumeMounts: + - mountPath: "/var/run/docker.sock" + name: docker-socket + readOnly: false + ports: + - name: http-server + containerPort: 8080 + volumes: + - name: docker-socket + hostPath: + path: "/var/run/docker.sock" diff --git a/docs/kubernetes-production/functions-service.yaml b/docs/kubernetes-production/functions-service.yaml new file mode 100644 index 000000000..7a4c8b31f --- /dev/null +++ b/docs/kubernetes-production/functions-service.yaml @@ -0,0 +1,14 @@ +--- +kind: Service +apiVersion: v1 +metadata: + name: functions + labels: + app: functions +spec: + ports: + - port: 8080 + targetPort: http-server + selector: + app: functions + type: LoadBalancer diff --git a/docs/kubernetes-production/postgresql-deployment.yaml b/docs/kubernetes-production/postgresql-deployment.yaml new file mode 100644 index 000000000..dabe22d71 --- /dev/null +++ b/docs/kubernetes-production/postgresql-deployment.yaml @@ -0,0 +1,17 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: postgresql-master +spec: + replicas: 1 + template: + metadata: + labels: + app: postgresql + role: datastore + spec: + containers: + - name: functions-postgresql + image: postgres + ports: + - containerPort: 5432 \ No newline at end of file diff --git a/docs/kubernetes-production/postgresql-service.yaml b/docs/kubernetes-production/postgresql-service.yaml new file mode 100644 index 000000000..861287d84 --- /dev/null +++ b/docs/kubernetes-production/postgresql-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgresql-master + labels: + app: postgresql + role: datastore +spec: + ports: + - port: 5432 + targetPort: 5432 + selector: + app: postgresql + role: datastore \ No newline at end of file diff --git a/docs/kubernetes-production/redis-deployment.yaml b/docs/kubernetes-production/redis-deployment.yaml new file mode 100644 index 000000000..3538603e3 --- /dev/null +++ b/docs/kubernetes-production/redis-deployment.yaml @@ -0,0 +1,17 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: redis-master +spec: + replicas: 1 + template: + metadata: + labels: + app: redis + role: mq + spec: + containers: + - name: functions-redis + image: redis + ports: + - containerPort: 6379 \ No newline at end of file diff --git a/docs/kubernetes-production/redis-service.yaml b/docs/kubernetes-production/redis-service.yaml new file mode 100644 index 000000000..be92ba845 --- /dev/null +++ b/docs/kubernetes-production/redis-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis-master + labels: + app: redis + role: mq +spec: + ports: + - port: 6379 + targetPort: 6379 + selector: + app: redis + role: mq \ No newline at end of file diff --git a/docs/kubernetes-quick/deployment.yaml b/docs/kubernetes-quick/deployment.yaml new file mode 100644 index 000000000..ba45ff24a --- /dev/null +++ b/docs/kubernetes-quick/deployment.yaml @@ -0,0 +1,33 @@ +--- +kind: Deployment +apiVersion: extensions/v1beta1 +metadata: + name: functions + labels: + app: functions +spec: + replicas: 1 + template: + metadata: + labels: + app: functions + spec: + containers: + - name: functions + image: iron/functions + securityContext: + privileged: true + env: + - name: DOCKER_HOST + value: unix:///var/run/docker.sock + volumeMounts: + - mountPath: "/var/run/docker.sock" + name: docker-socket + readOnly: false + ports: + - name: http-server + containerPort: 8080 + volumes: + - name: docker-socket + hostPath: + path: "/var/run/docker.sock" diff --git a/docs/kubernetes-quick/service.yaml b/docs/kubernetes-quick/service.yaml new file mode 100644 index 000000000..7a4c8b31f --- /dev/null +++ b/docs/kubernetes-quick/service.yaml @@ -0,0 +1,14 @@ +--- +kind: Service +apiVersion: v1 +metadata: + name: functions + labels: + app: functions +spec: + ports: + - port: 8080 + targetPort: http-server + selector: + app: functions + type: LoadBalancer diff --git a/docs/kubernetes.md b/docs/kubernetes.md new file mode 100644 index 000000000..637da105a --- /dev/null +++ b/docs/kubernetes.md @@ -0,0 +1,110 @@ +# HOWTO run IronFunction in Kubernetes at AWS + +*Prerequisite 1: it assumes you have a working Kubernetes, and a locally configured kubectl.* + +*Prerequisite 2: It assumes you are using Kubernetes 1.4 or newer.* + + +## Quickstart + +### Steps + +1. Start IronFunction in the Kubernetes cluster: +```ShellSession +$ cd docs/ +$ kubectl create -f kubernetes-quick +``` + +2. Once the daemon is started, check where it is listening for connections: + +```ShellSession +# kubectl describe svc functions + +Name: functions +Namespace: default +Labels: app=functions +Selector: app=functions +Type: LoadBalancer +IP: 10.0.116.122 +LoadBalancer Ingress: a23122e39900111e681ba0e29b70bb46-630391493.us-east-1.elb.amazonaws.com +Port: 8080/TCP +NodePort: 30802/TCP +Endpoints: 10.244.1.12:8080 +Session Affinity: None +Events: + FirstSeen LastSeen Count From SubobjectPath Type Reason Message + --------- -------- ----- ---- ------------- -------- ------ ------- + 22m 22m 1 {service-controller } Normal CreatingLoadBalancer Creating load balancer + 22m 22m 1 {service-controller } Normal CreatedLoadBalancer Created load balancer + +``` + +Note `a23122e39900111e681ba0e29b70bb46-630391493.us-east-1.elb.amazonaws.com` in `LoadBalancer Ingress` line, this is where the service is listening. + +3. Test the cluster: + +```ShellSession +$ export IRON_FUNCTION=$(kubectl get -o json svc functions | jq -r '.status.loadBalancer.ingress[0].hostname'):8080 + +$ curl -H "Content-Type: application/json" -X POST -d '{ "app": { "name":"myapp" } }' http://$IRON_FUNCTION/v1/apps +{"message":"App successfully created","app":{"name":"myapp","config":null}} + +$ curl -H "Content-Type: application/json" -X POST -d '{ "route": { "type": "sync", "path":"/hello-sync", "image":"iron/hello" } }' http://$IRON_FUNCTION/v1/apps/myapp/routes +{"message":"Route successfully created","route":{"appname":"myapp","path":"/hello-sync","image":"iron/hello","memory":128,"type":"sync","config":null}} + +$ curl -H "Content-Type: application/json" -X POST -d '{ "name":"Johnny" }' http://$IRON_FUNCTION/r/myapp/hello-sync +Hello Johnny! +``` + +## Production + +### Steps + +1. Start IronFunction and its dependencies: +```ShellSession +$ cd docs/ +$ kubectl create -f kubernetes-production +``` + +*Optionally, you might have both Redis and PostgreSQL started somewhere else, in this case, remember to update kubernetes-production/functions-config.yaml with the appropriate configuration.* + +2. Once the daemon is started, check where it is listening for connections: + +```ShellSession +# kubectl describe svc functions + +Name: functions +Namespace: default +Labels: app=functions +Selector: app=functions +Type: LoadBalancer +IP: 10.0.116.122 +LoadBalancer Ingress: a23122e39900111e681ba0e29b70bb46-630391493.us-east-1.elb.amazonaws.com +Port: 8080/TCP +NodePort: 30802/TCP +Endpoints: 10.244.1.12:8080 +Session Affinity: None +Events: + FirstSeen LastSeen Count From SubobjectPath Type Reason Message + --------- -------- ----- ---- ------------- -------- ------ ------- + 22m 22m 1 {service-controller } Normal CreatingLoadBalancer Creating load balancer + 22m 22m 1 {service-controller } Normal CreatedLoadBalancer Created load balancer + +``` + +Note `a23122e39900111e681ba0e29b70bb46-630391493.us-east-1.elb.amazonaws.com` in `LoadBalancer Ingress` line, this is where the service is listening. + +3. Test the cluster: + +```ShellSession +$ export IRON_FUNCTION=$(kubectl get -o json svc functions | jq -r '.status.loadBalancer.ingress[0].hostname'):8080 + +$ curl -H "Content-Type: application/json" -X POST -d '{ "app": { "name":"myapp" } }' http://$IRON_FUNCTION/v1/apps +{"message":"App successfully created","app":{"name":"myapp","config":null}} + +$ curl -H "Content-Type: application/json" -X POST -d '{ "route": { "type": "sync", "path":"/hello-sync", "image":"iron/hello" } }' http://$IRON_FUNCTION/v1/apps/myapp/routes +{"message":"Route successfully created","route":{"appname":"myapp","path":"/hello-sync","image":"iron/hello","memory":128,"type":"sync","config":null}} + +$ curl -H "Content-Type: application/json" -X POST -d '{ "name":"Johnny" }' http://$IRON_FUNCTION/r/myapp/hello-sync +Hello Johnny! +``` \ No newline at end of file