This Tech Bite was brought to you by Dario Pejčinović, Junior Software Engineer at Atlantbh.
Tech Bites are tips, tricks, snippets or explanations about various programming technologies and paradigms, which can help engineers with their everyday job.
In this Tech Bite we will show you how to deploy services using Kubernetes, a popular tool for the management of containerized applications. For tutorial purposes, two services will be deployed, fe-deploy, and be-deploy (each service is part of one image).
Spinning Pods using Deployment object
The smallest deployable unit in Kubernetes is a Pod, which represents a group of one or more containers. A Pod is usually managed by one more level of abstraction: Deployment, ReplicaSet, StatefulSet, etc. which enable us to scale up/down the desired number of Pods in a cluster (for the purpose of this episode, we will use Deployment Object). Because of the nature of the container, Pods are prone to sudden termination when a service inside of the container encounters an error and unexpectedly stops executing. In that case, Deployment is going to create a new, healthy Pod that replaces an ill, dying one. Below we have defined two Deployment objects, where be-deploy spins and manages three instances while fe-deploy spins and manages only one.
be-deployment.yaml fe-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: be-deploy labels: app: be spec: replicas: 3 selector: matchLabels: app: be template: metadata: labels: app: be spec: containers: - name: be image: be-image ports: - containerPort: 8080 apiVersion: apps/v1 kind: Deployment metadata: name: fe-deploy labels: app: fe spec: replicas: 1 selector: matchLabels: app: fe template: metadata: labels: app: fe spec: containers: - name: fe image: fe-image ports: - containerPort: 80
Exposing Pods using Service
Containers can communicate with other containers in the same Pod like they are on the same node, but by default cannot communicate with containers from another Pod. To allow communication between Pods across nodes of Cluster, a Kubernetes Service object is used. In this case, we will use ClusterIP (there are other options too) which make Pods reachable only from inside of the cluster.
be-service.yaml fe-service.yaml apiVersion: v1 kind: Service metadata: name: be-service spec: selector: app: be ports: - protocol: TCP port: 8080 targetPort: 8080 apiVersion: v1 kind: Service metadata: name: fe-service spec: selector: app: fe ports: - protocol: TCP port: 80 targetPort: 80
Accessing our application
After we have started our services and enabled them to communicate with each other, we have to expose our frontend outside of the cluster. For that purpose we can use an Ingress object, which routes incoming HTTP(S) requests to desired service (simple proxy). In order to use the HTTPS protocol, we need a certificate and private key so a secure connection between the user and Ingress can be established. To store sensitive information inside the Kubernetes cluster, we use Secret objects which can encode data using a base64 code scheme or can completely hide it.
fe-ingress.yaml apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: tls-example-ingress annotations: kubernetes.io/ingress.allow-http: false spec: tls: - hosts: - atlantbh.ba secretName: secret-tls rules: - host: atlantbh.ba http: paths: - path: /ui backend: serviceName: fe-service servicePort: 80 - path: /api backend: serviceName: be-service servicePort: 8080 ingress-secret.yaml apiVersion: v1 kind: Secret metadata: name: secret-tls type: kubernetes.io/tls data: tls.crt: base64-encoded-cert tls.key: base64-encoded-key
Each of the previously defined services can be created using
kubectl create -f object-name.yaml and can be deleted using the
kubectl delete -f object-name.yamlcommand.