Deployment¶
Requirements¶
You must have a Kubernetes cluster, which must have:
a namespace called emmental-platform (if you want to rename it, you must adapt all manifests)
a namespace called emmental-challenges (cannot be changed for now)
an Ingress controller enabled. For exemple, with Minikube, use
minikube addons enable ingressa networking plugin supporting Network Policies, like Calico (if using Minikube, it may be necessary to use
--network-plugin=cni --extra-config=kubeadm.pod-network-cidr=${POD_CIDR} \
with minikube start, see this issue).
Downloadable manifests¶
Kubernetes manifests can be downloaded here:
namespaces.yaml
authorization.yaml
back.yaml
front.yaml
mongo.yaml
Use these manifests one by one by using kubectl apply -f <filename.yaml>
or apply an entire manifest folder with kubectl apply -f <path/to/yaml/folder>
Note
To shut down what you just created, just replace apply by delete in above commands
Set up Namespaces¶
You need to have two namespaces, emmental-platform and emmental-challenges. You may use this manifest to create them:
--- apiVersion: v1 kind: Namespace metadata: name: emmental-platform --- apiVersion: v1 kind: Namespace metadata: name: emmental-challenges
Set up Network Policies¶
Warning
These manifests assume you use calico as a networking plugin.
Set up Role Service Bindings¶
We need to allow the platform to manage deployments and services. This manifest defines a ServiceAccount, then a ClusterRole and then bind them with a ClusterRoleBinding:
--- apiVersion: v1 kind: ServiceAccount metadata: name: api-emmental namespace: emmental-platform --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: challenge-instance-controller rules: - apiGroups: ["", "apps", "networking.k8s.io", "extensions"] # "" indicates the core API group resources: ["services", "deployments", "configmaps", "pods", "networkpolicies"] verbs: ["create", "patch", "read", "get", "list", "delete", "deletecollection"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: emmental-api-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: challenge-instance-controller subjects: - kind: ServiceAccount name: api-emmental namespace: emmental-platform
Platform deployment¶
back.yaml
front.yaml
mongo.yaml
Warning
This will expose the platform as a HTTP service. In production, you must deploy it in HTTPS!
First you need to clone the platform repository, and build the back and front images:
git clone <plateform adress>
cd plateform
make build-prod
Note
This creates two images named front and back.
Then, create a Kubernetes Deployment and Service to deploy the back:
--- apiVersion: apps/v1 kind: Deployment metadata: namespace: emmental-platform name: back spec: replicas: 1 selector: matchLabels: app: back tier: backend track: stable template: metadata: labels: app: back tier: backend track: stable spec: containers: - name: back image: back imagePullPolicy: Never ports: - containerPort: 5000 volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: name: configmap-back serviceAccountName: api-emmental --- apiVersion: v1 kind: Service metadata: namespace: emmental-platform name: back spec: selector: app: back tier: backend ports: - protocol: TCP port: 5000 targetPort: 5000
Note
You should adapt the number of replicas to your needs.
Do the same for the front, which is exposed by an ingress:
--- apiVersion: apps/v1 kind: Deployment metadata: namespace: emmental-platform name: frontend spec: replicas: 1 selector: matchLabels: app: emmental tier: frontend track: stable template: metadata: labels: app: emmental tier: frontend track: stable spec: containers: - name: front image: front imagePullPolicy: Never ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: namespace: emmental-platform name: front spec: selector: app: emmental tier: frontend ports: - protocol: TCP port: 8080 targetPort: 80 type: ClusterIP --- apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: namespace: emmental-platform name: front-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: backend: serviceName: front servicePort: 8080
To deploy a mongo database, add the next ressources, do not forget to customize the storage size and location on disk:
--- apiVersion: v1 kind: PersistentVolume metadata: name: mongo-pv-volume labels: type: local spec: storageClassName: manual capacity: storage: 10Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain hostPath: path: "/mnt/data/mongo" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: namespace: emmental-platform name: mongo-pv-claim spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 3Gi --- apiVersion: apps/v1 kind: Deployment metadata: namespace: emmental-platform name: mongo spec: selector: matchLabels: app: mongo role: master tier: backend replicas: 1 template: metadata: labels: app: mongo role: master tier: backend spec: containers: - name: mongo image: mongo ports: - containerPort: 27017 volumeMounts: - name: data mountPath: /data/db volumes: - name: data persistentVolumeClaim: claimName: mongo-pv-claim --- apiVersion: v1 kind: Service metadata: namespace: emmental-platform name: mongo labels: app: mongo role: master tier: backend spec: ports: - port: 27017 targetPort: 27017 selector: app: mongo role: master tier: backend
Warning
Using local storage will not work on multi-node clusters.