Configurator

Configurator is an open-source project that version controls and keeps Kubernetes ConfigMaps and Secrets in sync with the deployments. Configurator uses CRDs to create CustomConfigMaps and CustomSecrets that in turn creates ConfigMaps and Secrets with a postfix. As and when a change is detected in a CustomConfigMap or a CustomSecret, Configurator automatically generates a new ConfigMap with a new postfix. This acts as a version controlling system for ConfigMaps. A change in a ConfigMap not only creates a new ConfigMap version but also rolls out a new deployment version across all the deployments using the ConfigMap. This enables both rolling update and rollback of ConfigMaps in sync with the deployment versions.

This blog will focus on the following motives:

  • Installing Configurator using the helm chart.
  • Customizing Configurator helm chart based on requirements.
  • Contributing back to the Configurator project.

System Requirements

Make sure that you have installed helm in your machine and you are connected to a Kubernetes cluster. The chart is qualified for helm version > v3 & Kube version v1.20.8. Follow the documentation from the link to install helm: https://helm.sh/docs/helm/helm_version/

helm version
version.BuildInfo{Version:"v3.0.2", GitCommit:"19e47ee3283ae98139d98460de796c1be1e3975f", GitTreeState:"clean", GoVersion:"go1.13.5"}

Installing Configurator using helm chart

Follow the below steps to directly deploy the Configurator helm package. Make sure that a namespace ‘configurator’ already exists in your cluster. If not, create a namespace with the following command.

kubectl create namespace configurator

Add the configurator helm repository, by executing the following command :

helm repo add gopaddle_configurator https://gopaddle-io.github.io/configurator/helm/

Once the command is executed, verify the repository by running the command below. You must see the configurator_helm repo in the list.

helm repo list

The output must be similar to this:

NAME                   URL
hashicorp              https://helm.releases.hashicorp.com
gopaddle_configurator  https://gopaddleio.github.io/configurator/helm/

Once you’ve verified the repo, install the helm chart with the following command: helm install <release_name> <repo_name/chart_name>

helm install release1.0.0 gopaddle_configurator/configurator

This installs the Configurator CRDs and the controller in the ‘configurator’ namespace. After you install the helm chart, verify by listing the resources in the corresponding namespace using the following commands.

kubectl get pods -n configurator
kubectl get crds -n configurator
kubectl get serviceaccounts -n configurator
kubectl get clusterrolebindings -n configurator

The configurator is now ready for use. Here is a reference blog on how to use configurator with the deployments: https://blog.gopaddle.io/2021/04/01/strange-things-you-never-knew-about-kubernetes-configmaps-on-day-one/

Customizing Configurator helm chart based on requirements

Sometimes, you may wish to change the Configurator image name, Docker repository, image tag or even include other service charts along with Configurator. Modifying the Configurator helm is pretty straightforward. Make sure you’ve cloned the Configurator GitHub project before proceeding with the next steps.

To clone the project, run the following command:

git clone https://github.com/gopaddle-io/configurator.git

The helm package needs to be unpacked to modify the helm chart. The zip file will be present at the path configurator/helm in the Configurator project. Choose this option when you want to modify the helm chart configuration. Unzip the file with the following command.

tar -zxvf <path to .tgz file>

This will extract the contents of the chart in a folder. Once you extract, the helm chart’s file system tree will look like this:

configurator
├── charts
├── Chart.yaml
├── crds
│ ├── crd-customConfigMap.yaml
│ └── crd-customSecret.yaml
├── templates
│ ├── configurator-clusterrolebinding.yaml
│ ├── configurator-clusterrole.yaml
│ ├── configurator-deployment.yaml
│ ├── configurator-serviceaccount.yaml
│ └── tests
└── values.yaml

The crds directory contains the custom resource definition files — crd-customConfigMap.yaml & crd-customSecret.yaml. The templates directory contains the resource’s yaml files, in our case, it contains the roles and role bindings and the configurator service definitions. The charts directory is empty by default. This folder can be used to add your application charts that use Configurator Custom Resource. The Chart.yaml file contains information about the helm, like the chart’s name, description, type etc.

# Default values for my_chart.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
replicas: 1
namespace: configurator
image: gopaddle/configurator:latest

You can edit the values.yaml file to your requirements like changing the namespace, replica_count or the image name, docker repository or the image tag. Make sure that the namespace used in the values.yaml exists in the cluster before you do a helm install. Once the necessary configuration is done, execute the following command to install the charts into your cluster: helm install <release_name> <chart_name>

helm install release1.0.0 configurator

This will install the helm chart inside the cluster with the new configurations.

Contributing back to the configurator project

To contribute the helm changes back to the Configurator project, you need to package the helm chart with the following command :

helm package <path to helm chart>

This command will package the charts to a .tgz file. After packaging the helm, you need to give a pull request for code review & merge.

You can take a look at this open-source project @ https://github.com/gopaddle-io/configurator.git.

For any queries on how to use or how to contribute to the project, you can reach us on our discord server — https://discord.gg/dr24Z4BmP8

Image courtesy — https://www.freepik.com/vectors/technology Technology vector created by stories — www.freepik.com

Deploying on Kubernetes is one complex task, but dealing with surprises during maintenance is another. I can talk from my own experience of maintaining our gopaddle platform deployments on Kubernetes for more than a year now. Even with careful planning and collective knowledge from within the team, there are still hidden challenges in keeping the deployments intact. We get to learn those hidden challenges only by running the production systems on kubernetes for a while. This blog is one such wisdom we learnt. I would like to share our experience with ConfigMaps and what solution we built (open source) to overcome some trouble with ConfigMaps. For the rest of the blog, I am going to be focusing on ConfigMaps, but secrets also have the same set of challenges. Though I have referenced deployments through out the blog, the given scenario and solution exists for kubernetes secrets as well.

ConfigMaps and Secrets are often overlooked topics when it comes to Cloud Native Deployments. But they can add unforeseen challenges during application maintenance. Let me first introduce you to what ConfigMaps are.

ConfigMaps are Kubernetes resources that are used to store application configurations. It enables build time and run time attribute segregation in a cloud native deployment. Say by using ConfigMaps, you do not have to package application configurations along with your container images. Thus changing application configurations does not require the entire application to be rebuilt. We leverage ConfigMaps to keep our applications 12-factor compatible. In a nutshell, ConfigMaps are:

  • Collection of regular files or key/value pairs
  • Can be used to set Environment variables inside a container (using ValueFrom: ConfigMapRef to refer to values defined in ConfigMaps)
  • Can be mounted as directories inside containers (using VolumeMounts/MountPath keywords) and all the files within ConfigMaps get mounted inside the container on the mountPath provided.
  • Shared across deployments/replicas
  • Confined to a namespace
  • Created from files, literals, kustomize configMapGenerator
  • Replaces all files within the mount path : Since ConfigMaps are mounted inside the container on a given mount path, any existing files and folders within the container will not be available.

Here is an example of how ConfigMaps are defined and referenced inside a deployment specification.

Example of defining and using ConfigMaps inside deployment specifications

Hidden challenges of ConfigMaps

Some of the challenges with ConfigMaps are realized as soon as they are mounted inside the container. But some are unearthered only during maintenance. Following are some challenges we have observed :

  1. Can’t execute files in ConfigMaps : Starting from K8s 1.9.6, ConfigMaps get mounted as read-only files by default. Hence you may not be able to execute or run these files. Say, if you are planning on executing these files as container EntryPoint or CMD ARGs, then container may crash during startup as it cannot execute these read-only files. If you have recently upgraded the cluster version, then your deployments may break due this. Please check this K8s issue for information on how to configure ReadOnlyAPIDataVolumes to mount ConfigMaps as ReadWrite files.
  2. Deployments & ConfigMaps are loosely coupled, ie., they follow different lifecycle, but updating the contents of a ConfigMap automatically reflects inside the Pods. More often, applications running inside the containers need a restart to pick the new changes. But, applications are clueless of the changes. These changes are noticed during a scale up/down or a Pod restart event when the application inside the container gets restarted.
  3. No Versioning/No Rollbacks of ConfigMaps: ie when deployments are rolled back, it does not roll back the contents of the ConfigMaps.

The last two issues are the resultant of the mutable nature of ConfigMaps.

ConfigMaps are mutable

ConfigMaps are mutable ie., they can be edited. Every time a change is made, it is the same ConfigMap that gets updated. There are no revisions. Let me illustrate this with an example.

ConfigMaps are mutable

We have a ConfigMap, which is referenced in two different deployments. When you change the ConfigMap, the contents of the ConfigMap changes inside the deployments. When the deployments are rolled back, they still point to the current content of the ConfigMap. This can cause a problem when your application is expecting something but it actually sees something else. Deployments do not maintain any state regarding the ConfigMap changes.

Workarounds

ConfigMaps – Workarounds
  1. Smart apps: Applications can be designed in such a way that they constantly poll for changes in the ConfigMaps. This approach still cannot address the roll back issue.
  2. Induced Rolling Update: Another common approach is to hash the contents of the ConfigMap in to the deployment. When the ConfigMap changes, the hash changes and that automatically triggers a rolling update on the deployment. But even in this case, rolling back a deployment does not roll back to the previous content of the ConfigMap. Here is a reference to how ConfigMap hash can be used.
  3. Immutable ConfigMaps: The next option is to use ConfigMap as an immutable content. This feature was introduced in kubernetes 1.19. When this feature is turned on, you cannot update a ConfigMap and thus you can avoid all the associated problems.

Versioning the ConfigMaps

The ideal solution to keep the deployments and the ConfigMaps in sync is to version control the ConfigMaps and reference them in the deployments.

Versioning ConfigMaps
  • In the above example, when the contents of the ConfigMap version 1 is updated, it creates a new ConfigMap version 2. When the deployment specification is updated with ConfigMap version 2, it automatically triggers a rolling update and creates a new deployment version. When the deployment is rolled back, the rolled back version will reference ConfigMap v1. Thus ConfigMaps and deployments go hand in hand.
  • To make this work, we need to :
  • Version ConfigMaps whenever a change is committed to a ConfigMap
  • Automatically update ConfigMap versions in Deployment Specifications where ever it being referenced
  • Purge unused ConfigMaps periodically – Since ConfigMaps are shared resources across deployments and since each deployment may have a different revision history limits, we must consider checking all the revisions of all the deployments within the namespace to know if a ConfigMap is being used and purge accordingly.

Introducing Configurator

Configurator is an open source solution from gopaddle that makes use of Custom Resource Definitions (CRDs) for ConfigMaps/Secrets and an operator to automate the above mentioned steps. ConfigMaps and Secrets are now defined as CustomConfigMaps and CustomSecrets which are custom resources constantly monitored by the Configurator.

How it solves the problem

When a new CustomConfigMap or a CustomSecret resource is created, it generates a ConfigMap or a Secret with a postfix. This ConfigMap along with the post fix need to be added to the deployments/statefulsets initially.

From then on, if any change to the CustomConfigMap or CustomSecret is detected, configurator automatically updates all the deployments/statefulsets referencing the specific ConfigMap/Secret with a postfix. Configurator heavily depends on the configMapName in the CustomConfigMap and the labels in the deployment/statefulset specifications.

In the above example you can see that the example-customConfigMap.yaml creates a CustomConfigMap with the configMapName as testconfig. As soon as the CustomConfigMap is created, it automatically creates a ConfigMap testconfig-sn8ya. We need to manually add this ConfigMapName testconfig and the postfix sn8ya in the deployment’s metadata.labels as testconfig: sn8ya and also use the ConfigMapName testconfig-sn8ya in the volumes section.

From now on, user does not have to manage ConfigMaps directly.

Any change required in the ConfigMap or Secret needs to be done through the CustomConfigMap or CustomSecret.

When the CustomConfigMap is updated with the new content in the data section, it automatically generates a new ConfigMap testconfig-10jov and updates the deployment with the new ConfigMap name under the volumes and the metadata.label section.

Configurator purges unused ConfigMaps and Secret every 5 mins. It scans the replicaset or controllerRevision of all the deployments and statefulsets in the namespace and checks if the metadata.label exists for the ConfigMap. If there are no references, it purges the ConfigMap version.

How to use it ?

Download run the YAML files from our repository here and install them in your cluster.

kubectl apply -f deploy/crd-customConfigMap.yaml
kubectl apply -f deploy/crd-customSecret.yaml
kubectl create ns configurator
kubectl apply -f deploy/configurator-clusterrole.yaml
kubectl apply -f deploy/configurator-clusterrolebinding.yaml
kubectl apply -f deploy/configurator-serviceaccount.yaml
kubectl apply -f deploy/configurator-deployment.yaml

Once the configurator is deployed into the cluster, start creating CustomConfigMap or CustomSecret.

 example-customConfigMap.yaml

apiVersion: "configurator.gopaddle.io/v1alpha1"
kind: CustomConfigMap
metadata:
 name: configtest
 namespace: test
spec:
  configMapName: testconfig
  data:
   application.properties: |
    FOO=Bar

Create CustomConfigMap in cluster

Kubectl apply -f example-customConfigMap.yaml 

List the ConfigMaps

kubectl get configMap -n test
NAME               DATA   AGE
testconfig-sn8ya   1      7s

Copy the ConfigMap name and add the ConfigMap name in the deployment.yaml file at the volume level and metadata label level. In metadata level split the ConfigMap name and postfix separately and add that in the label.

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: busybox-deployment
  labels:
   testconfig: sn8ya
    app: busybox
spec:
  replicas: 1
  revisionHistoryLimit: 1
  strategy: 
    type: RollingUpdate
  selector:
    matchLabels:
      app: busybox
  template:
    metadata:
      labels:
        app: busybox
    spec:
      containers:
      - name: busybox
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ['sh', '-c', 'echo Container 1 is Running ; sleep 3600']
        volumeMounts:
        - mountPath: /test
          name: test-config
      volumes:
      - name: test-config
        configMap:
          name: testconfig-sn8ya

Edit the CustomConfigMap and list the ConfigMap. You can see new ConfigMap name with a postfix.

Kubectl edit ccm configtest  -n test
Kubectl list cm -n test
NAME               DATA   AGE
testconfig-10jov   1      10s
testconfig-sn8ya   1      111s

Now check the deployment. You can see that it is updated with new ConfigMap and metadata label.

kubectl get deployment busybox-deployment -n test -o yaml 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: busybox-deployment
  labels:
  testconfig: 10jov
    app: busybox
spec:
  replicas: 1
  revisionHistoryLimit: 1
  strategy: 
    type: RollingUpdate
  selector:
    matchLabels:
      app: busybox
  template:
    metadata:
      labels:
        app: busybox
    spec:
      containers:
      - name: busybox
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ['sh', '-c', 'echo Container 1 is Running ; sleep 3600']
        volumeMounts:
        - mountPath: /test
          name: test-config
      volumes:
      - name: test-config
        configMap:
          name: testconfig-10jov

Give configurator a try and share your feedback with us. If you are interested in contributing to the project, you can reach out to us. The project can be cloned from https://github.com/gopaddle-io/configurator

Continuous Integration (CI) and Rolling Update to a kubernetes service can be achieved seamlessly when using gopaddle Deck and Propeller together. gopaddle Deck does an automatic source to image conversion and uses Kubernetes based build environments to build Docker images. gopaddle Propeller helps to create services and application templates that can be deployed across different kubernetes environments. You can enable Continuous Integration in Deck, such that a Docker build is triggered as soon as a code commit or a code merge happens in github. When Deck and Propeller are used together, a seamless CI/CD can be achieved with a robust version controlling across the kubernetes resources. However, in some scenarios, you may choose to use a different tool/platform in place of Deck to build the docker images and use Propeller deploying and managing the applications. For example, you may choose to use github Actions and then integrate with Propeller for rolling updates. Here is a comparison of github Actions vs Deck and when one can be used instead of the other. Irrespective of the build tool used, gopaddle exposes APIs that can be integrated with any third party tools.

github Actionsgopaddle Deck
DockerfileMust pre-exist in the github repo.Auto-generate Dockerfile or use an existing Dockerfile
Build Environment* On-demand Virtual Hosted environments or Pre-provisioned self-hosted environments. Self hosted environments can be physical or virtual machines or containers.
* Requires configuration effort to setup self-hosted environments
* Runs on VMs or on Containers. Scaling up/down the environments requires requires automation.
* On-demand: Runs inside your kubernetes cluster as isolated build jobs with a specified CPU/Mem capacity.
* Requires no additional effort.
* Uses shared kubernetes environment and can save cost as the environments scales up/down automatically based on build jobs.
Shared EnvironmentsCan be dedicated for a single repo or shared within/ across organizationsCan be run on a shared kubernetes cluster, but new jobs are created for every build.
OS support for build environmentsLinux, Windows and MacOS. For complete list of OS supported check here.Bring your own OS image. Any Linux Operating system.
Architecturesx64 – Linux, macOS, Windows.
ARM64 – Linux only.
ARM32 – Linux only.
Intel x86_64  – Linux only.
AMD64 – Linux only.
ARM64 – Linux only.
Multi-arch – Linux only.
SubscriptionHosted environments has free minutes beyond which per-minute rates are applied. Self-hosted environments are maintained by end-users on their local infrastructure.Billed based on build concurrency and total number of builds.
github Actions vs gopaddle Deck

If you choose to use github actions for building the containers, then this blog covers the method of integrating github Actions with gopaddle propeller.

Here are some simple steps to follow:

  1. Create Github Actions
  2. Register Docker Registry in gopaddle
  3. Create an Image based container in gopaddle
  4. Create necessary artifacts in gopaddle and deploy the service on a Kubernetes environment
  5. Generate gopaddle API token
  6. Update github actions to invoke gopaddle API

Let us explore each of these steps in detail.

Trigger Rolling Update directly from github actions

Create Github Actions

As the first step, we will set the github actions to build a docker container. You can use github secrets to store sensitive information like credentials and tokens. Then create a github workflow using those secrets. We will be using Azure Docker Registry to push the docker image. Hence we will use the azure/docker-login@v1 plugin in the workflow.

  1. Let us create the secrets in github repository. Under settings option in github respository, edit Secrets and Add a New respository secret. We will add the Azure credentials in the github secret for the time being. But as we progress through the remaining steps, we will need to add the secrets for gopaddle API token as well. You can follow the steps documented under Azure ACR Registry section here to create an Azure Registry. Here is the list of secrets we need in order to use Azure Registry. You will need these information while registering the Azure Registry in gopaddle as well.
    • REGISTRY_LOGIN_SERVER
    • REGISTRY_USERNAME
    • REGISTRY_PASSWORD
github repository secrets

2. Now let us create the .github/workflows folder in the repository. Go to the workflow tab and create the yaml file to build your source code. Your github actions task would look like this to build and push the image to the docker registry. petclinic is the name of the docker image and we will use the github commit ID as the docker image tag. By using the commit ID as the tag, we can relate the docker image to the commit that triggered the build for future debugging.

    - name: 'Build and push image'
      uses: azure/docker-login@v1
      with:
        login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
        username: ${{ secrets.REGISTRY_USERNAME }}
        password: ${{ secrets.REGISTRY_PASSWORD }}
    - run: |
            docker build . -t ${{ secrets.REGISTRY_LOGIN_SERVER }}/petclinic:${{ github.sha }}
            docker push ${{ secrets.REGISTRY_LOGIN_SERVER }}/petclinic:${{ github.sha }}

3. Execute github actions once, so that a docker image is created and pushed to docker registry. We will be using this image in the next steps.

Register Docker Registry in gopaddle

We will be using the image created in earlier step to deploy an application in gopaddle. Once an application is deployed, we can perform further rolling updates on that application. We can automate this initial deployment process as well using gopaddle APIs. But for the time being, we will manually deploy an application using gopaddle UI. To create the gopaddle artifacts, Docker Registry has to be registered with gopaddle, so that gopaddle knows the source from which a docker image can be pulled and deployed.

4. Register the Azure Registry in gopaddle as described here.

Create necessary artifacts in gopaddle and deploy the service on a Kubernetes environment

5. We need to create 3 resources in gopaddle.

(a) Container : Create an image based container in gopaddle using the image created in the earlier step as described here. Once the container is created, note down the container ID by viewing the container and extracting the ID from the browser URL.

(b) Service : Create a Service and add the container to the service as described here. Once the service is created, note down the service ID by viewing the service and extracting the ID from the browser URL.

(c) Deployment Template : Create a Deployment Template and add the Service to the template.

6. Create a Kubernetes cluster as described here and deploy the template on the Kubernetes cluster to create a running application.

7. Once the application is launched, view the application and gather the application ID from the browser URL.

Using the container ID, service ID and the application ID, we can trigger the rolling update on the specific container within an application as soon as the build is complete.

Generate gopaddle API token

gopaddle APIs can be securely invoked by using an API token. A user can generate one or more API tokens. A role defines the permissions for a user. A role can be assigned to a user to restrict actions within gopaddle. Let us first create a role, a user and then assign the role to the user. Once the user is created, we will generate an API token.

8. In the gopaddle portal, under user profile, navigate to Teams -> Access Control Lists and create a new role with access to All Services and All Permissions for the time being.

gopaddle – create a role with All Permissions

12. Under the Users tab, create a user and assign the role.

13. Click on User actions and Add a token

Update github actions to invoke gopaddle API

Now we have the necessary details to invoke gopaddle APIs.

  • Container ID
  • Service ID
  • Application ID
  • API Token

14. Add this API token in the github secrets.

15. Update the github actions code to invoke gopaddle API as below.

Your github actions YAML would look like this: We will be using fjogeleit/http-request-action@master github plugin to trigger an API call.

# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven

name: Java CI with Maven

on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8
      - name: Build with Maven
        run: mvn -B package --file pom.xml
      - name: "Build and push image"
        uses: azure/docker-login@v1
        with:
          login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
          username: ${{ secrets.REGISTRY_USERNAME }}
          password: ${{ secrets.REGISTRY_PASSWORD }}
      - run: |
          docker build . -t ${{ secrets.REGISTRY_LOGIN_SERVER }}/petclinic:${{ github.sha }}
          docker push ${{ secrets.REGISTRY_LOGIN_SERVER }}/petclinic:${{ github.sha }}
      - run: echo "DESC=$(echo -n ${{ github.event.head_commit.message }} | base64)" >> $GITHUB_ENV
      - name: Deploy Stage
        uses: fjogeleit/http-request-action@master
        with:
          url: "https://portal.gopaddle.io/gateway/v1/application/appsa8218974c6043c4fd2cbd9ac6a71035fcbcf"
          method: "PUT"
          bearerToken: ${{ secrets.BEARER_TOKEN }}
          data: '{"updateType":"buildUpdate","deploymentTemplateVersion":"draft","serviceGroups":[{"name":"spring-petclinic","id":"sg63e2f795sg62e6sg4cd7sgbaefsg4e572ff17787","version":"draft","services":[{"id":"svcea1ce6dcdccaccc4c64cabbec84f5b0f495ee","serviceVersion":"draft","releaseConfig":{"image":"${{ secrets.REGISTRY_LOGIN_SERVER }}/petclinic:${{ github.sha }}"}}],"description":"${{ env.DESC }}"}]}'

Note that, in the above YAML, BEARER_TOKEN is the API token, the URL contains the application ID, id under services array is the container ID, id under serviceGroups is the service ID. Also note that the commit description is encoded in base64 format and then used as the description in rolling update.

CI/CD pipeline is now ready.

Let us now commit a few changes to the github code and this triggers the workflow.

In the gopaddle portal, you can check the version history under the application. We can see that a new rolling update is triggered.

We can also extend this pipeline by triggering a Jenkins pipeline instead of triggering gopaddle APIs, so that a few integration tests can be run before performing a rolling update. We can use the payload described in the YAML file to trigger gopaddle API from Jenkins pipeline as well. Hope you find this blog useful.

Introduction

In order to comply with the Payment Card Industry Data Security Standard (PCI DSS), application access, transaction and system logs need to be monitored. Fluentd is an open source, distributed logging and aggregation framework. It offers a unified logging layer to collate & filter logs of different nature like access logs, application logs and system logs. Fluentd also helps to aggregate, analyse and archive these logs. Kubernetes uses the glog library module for logging Fluentd for application monitoring.

For application (microservice) log monitoring, a sidecar container is suggested pattern for deploying Fluentd within the same pod where the application lives. A shared volume between the application container and the Fluentd container holds the log files for the containers. Fluentd uses the shared volume as the data input and the Google Cloud Logging Service as the data output, provided the cluster is on Google Compute and the VM has cloud-logging.write scope.

The Daemon Set feature, which went GA in Kubernetes 1.2, allows you to deploy Fluentd as a pod across all the nodes in your cluster, instead of deploying them specific to an application.

Technical Implementation

Daemon Set is an extended feature available in Kubernetes 1.2 beta. Some of the typical use cases of Daemon Sets are log aggregation, monitoring services that need to be run on a selected set of nodes within a cluster. Daemon Sets are headless services and are very different from replication controllers. Replication controllers are stateless services that can scaled up or down and can be scheduled across different nodes, whereas Daemon Sets help in performing specific tasks within selected nodes.

Benefits of Daemon Sets

  • Daemon Sets can be deployed the same way as deploying an application on Kubernetes
  • Daemon Sets can be deployed on a selected set of nodes with specific tags. Whenever a new node is added with a similar tag, Daemons get deployed automatically.
  • Daemon Sets with different resource requirements like CPU, memory & storage can be grouped and deployed on selected nodes
  • Running Daemon Sets as separate PODs & containers within a node gives better resource isolation rather than running them as simple daemons within the node

Fluentd Use Case

Let us consider a use case with a 2-tier application deployment using goPaddle. The application design composes of ngnix and tomcat services. Using goPaddle, each of these services can be deployed as scalable micro-services using POD per container architecture shown below. Each service will have its own replication controller and can scale independently.
fluentd

The services are deployed across a 3 node Kubernetes 1.2 cluster.

Fluentd is available as an add-on component in goPaddle designer. It can be configured to accept log folder(s) and write logs to an external MongoDB service. Fluentd can be created as a single service design and can be deployed the same way as any other service. At the time of deployment, goPaddle provides an option to select the nodes where it needs to be deployed.

In all the selected nodes, Fluentd gets deployed as a Daemon Set and gets configured automatically to collect the logs from the specified folders. goPaddle deploys the services and the daemons using the Sidecar Pods pattern (similar to Sidecar containers pattern) where the pods share the volumes for log read/write.

Best practices

As a best practice, if the application loggers are configured to prepend the host IPs, then the aggregated logs would be prepended with the Pod IPs which can later be used to filter the logs from specific service instance.

Benefits:

By deploying Fluentd as a Daemon Set using goPaddle,

  1. It can be customized to monitor specific or all applications running within the same node
  2. It can collect logs from specific log files across all applications within the same node
  3. It can collect system logs across all the containers within the same node
  4. Since they are run as a separate pod, they run outside the application scaling rules
  5. Use custom log data outputs other than Google Cloud Logging
  6. Since it is run as a Daemon Set, it is ensured that is always in running state

Note:
Using goPaddle, it is also possible to deploy a Daemon Set in ambassador pod pattern (similar to ambassador container pattern) where the application Pod can communicate with the Daemon Set pod using localhost reference. A typical use case would be to deploy etcd services within a Pod and the applications can access etcd for key/value store and retrieval.

2016 being the year of DevOps, IT organizations are already looking at scale-out and economies of scale, while e-commerce companies have understood the impact of agile delivery and zero downtime of their applications. As Gartner predicted, it is becoming a mainstream strategy employed by 25 per cent of Global 2000 organisations. While the need for DevOps is building up, micro-services based architecture is becoming the key enabler for rapid application delivery. Micro-services are sizable units of execution that are independent, polyglot and reusable. Independent teams / developers can make versions of these micro-services, package them as container such as Docker and deploy them on an infrastructure of their choice. Container Clusters like Kubernetes provide a distributed and portable platform that can manage the lifecycle of these containers and provide consistent environments so that applications can be moved painlessly across datacenter and clouds.

While a spectrum of DevOps ready solutions are emerging in the market, a platform that is focused on continuous build, integration and deployment for micro-services will be a huge cost & time saving solution for businesses.

Customers have been using goPaddle, for continuous build and deployments since last year. With the new release, goPaddle is optimized for Google Cloud, thus making authentication, on-boarding micro-services and cluster provisioning simple and seamless for Google Cloud Developers. goPaddle provides a powerful yet simple designer interface, that developers can use to drag drop components to create micro-service designs and generate container/cluster specifications on the fly. These designs can then be deployed on to Google Container Engine (GKE) or to a cluster of their choice. Developers can leverage Google Container Registry (GCR) or use Docker Hub for storing/retrieving the container images. As these features signify, goPaddle has moved the infrastructure management hassles away from the developers, while the developers can focus on building their applications.

While adding simplicity, goPaddle also gives the traceability and control to audit and monitor the applications. In general, log aggregation platforms like fluentd have greatly been in use by the developers and system administrators to monitor the system, application and access logs. goPaddle v2.0 brings in the support for fluentd leveraging the newest features in Kubernetes v1.2. With goPaddle, fluentd can be deployed on selective cluster infrastructure to aggregate logs from micro-services running within those infrastructure.

gopaddle is available as a hosted version at https://gopaddle.io and as enterprise ready on-premise version with extended support. For more information, get in touch with the Bluemeric team at info@bluemeric.com.

Ready To Modernize Applications The Easy Way ?

Try our 15 day free trial