Meet the 8 Sponsors of 2021 State of DevOps Reports - Build What's Next
Blog

Meet the 8 Sponsors of 2021 State of DevOps Reports

3257

Of your peers have already read this article.

4:00 Minutes

The most insightful time you'll spend today!

State of DevOps report is an independent research based on how teams and companies drive excellence with tech using DevOps practices and at various stages of their DevOps journey. Read blog to know the 8 sponsors powering the DevOps community.

Google Cloud and the DORA research team are excited to announce our eight sponsors for the 2021 State of DevOps report. We recently launched the 2021 State of DevOps survey, a 25-min survey for the DevOps community to share how they are using DevOps to improve software delivery performance. So if you haven’t taken the survey yet, this is your chance! 

For those unfamiliar with the State Of DevOps report, it is the largest and longest running research of its kind. It provides an independent view into how teams and companies can drive powerful business outcomes, no matter what stage of the DevOps journey

With the State of DevOps reports we aim to capture how teams and companies are driving excellence in technology delivery through the implementation of DevOps practices, no matter what stage of the DevOps journey your team is in. If you’re wondering how your team measures up in your industry take our DevOps Quick Check and discover which capabilities you should focus on to improve your performance.

To capture a diverse array of information on how those in the DevOps community are performing, our eight sponsors of the 2021 State of DevOps survey are focussed on helping organizations of all sizes and industries to develop and deliver software faster across the whole DevOps lifecycle. Captured below, you’ll find more information on our sponsors for this year and why they chose to sponsor the State Of the DevOps 2021 Report.

Armory

armory

Armory enables enterprise companies to ship better software, faster through trusted, reliable, safe, and secure deployments — at its core, Armory is powered by Spinnaker OSS.

“Armory exists to unlock innovation through software. To achieve this, we help enterprises reliably deploy software at scale, naturally aligning with DevOps practices to improve software delivery performance. Given this, we applaud efforts like the State of DevOps Report that provides an independent view into the practices and capabilities that organizations can employ to drive better performance.” 

Carl Timm, Senior Director of Product Marketing at Armory

CircleCI

circleci

The world’s best software teams deliver quality code, confidently, with CircleCI. The world’s best software teams use CircleCI to go from next-up to feature shipped, at the speed ambitious businesses require. 

“Though the DevOps space is only over a decade old, it moves incredibly quickly. Google’s State of DevOps report is both a reflection and projection of the industry, capturing how DevOps culture drives business results and where DevOps practitioners can look to improve. At CircleCI, we rely heavily on this survey data to glean valuable insights into our market and our customers overall. We also build upon these insights to guide our own research into how engineering teams move code through pipelines in our annual State of Software Delivery report. Taken together, this research highlights teams’ reported and actual behavior and paints a vibrant picture of how technology-driven organizations drive for success.”

Emma Webb, VP, Corporate Communications, CircleCI 

Continuous Delivery Foundation

cdf

CD Foundation is an open-source community improving the world’s ability to deliver software with security and speed.

“Good decision-making is based on good data. Open source is a critical piece of the technology roadmap for DevOps, and the 2021 State of DevOps Report will provide actionable information for high performing teams in organizations of all types and sizes. The report will show where open source and DevOps intersect, and in a space that is changing so quickly, new relevant data is critical,” said Tracy Miranda, Continuous Delivery Foundation Executive Director. “CD Foundation members are deeply involved with producing this annual report, with over 10 years of historic research. Thank you to Google and our other members who have worked so hard on it. This report is a tangible result of working together.”

Tracy Miranda, Continuous Delivery Foundation Executive Director

Deloitte

deloitte

Deloitte provides audit and assurance, tax, consulting, and risk and financial advisory services to a broad cross-section of the largest corporations and governmental agencies. At Deloitte, they are continuously evolving how they work and how they look at marketplace challenges so they can continually deliver measurable, sustainable results for their clients and communities.

“Software delivery is evolving rapidly and we know our customers need unique and compelling insights to make the right decisions. State of DevOps is a widely used report and considered as an Industry standard to understand the drivers for excellence in Software Development and Delivery. Deloitte is excited to help the team at DORA and Google Cloud in publishing this report through our sponsoring since we believe the insights from this report will help make software delivery better.” 

Manoj Mishra, Consulting Managing Director, Deloitte Consulting LLP

GitLab

gitlab

GitLab is the open DevOps platform built from the ground up as a single application for all stages of the DevOps lifecycle enabling Product, Development, QA, Security, and Operations teams to work concurrently on the same project.

“We’re happy to sponsor the DORA Report and the vital work behind it. The more we understand the DevOps journey, the better we and our GitLab community can contribute to its future. We’re particularly interested to see this year’s results and the impact COVID-19 and remote work have had on DevOps. We appreciate the chance to be part of this exciting, informative process.”

Brendon O’Leary, Senior Developer Evangelist

Liquibase

liquibase

Liquibase helps millions of developers easily manage database schema changes by enabling teams to track, version, and deploy database changes by delivering on the promise of CI/CD for the database.

“With their rigorous methodology, the DORA research team delivers actionable information with the simple goal of helping organizations of any size accelerate the development and delivery of software. Liquibase is honored to sponsor the 2021 State of DevOps Report and its role in helping so many organizations build value for their customers and shareholders”

Matt Geise, VP of Marketing at Liquibase

PagerDuty

pagerduty

PagerDuty is a digital operations management platform that empowers the right action, when seconds matter.

“As a leader in digital operations management, PagerDuty is proud to sponsor this year’s report as it aligns with our dedication to helping DevOps professionals make better decisions. This report will inform tech and business leaders about the trends/challenges developers are facing and the opportunities there are to accelerate their own DevOps transformation.” 

Carolyn Guss, VP of Corporate Marketing

SysDig

sysdig

Sysdig is driving the secure DevOps movement, empowering organizations to confidently secure containers, Kubernetes and cloud.

“There is a learning curve with all new technology, cloud is no exception. Learning from mistakes and sharing best practices is how we will ultimately ship secure applications, faster. For seven years, DORA and Google have partnered to understand the State of DevOps to help vendors and cloud practitioners to learn from each other and implement standards for best practices,”

Loris Degioanni, CTO and founder of Sysdig

Google Cloud, the DORA team, and our sponsors are very excited about this year’s report. We look forward to hearing from you, your colleagues, and networks about how DevOps is integrated into your workflow and ways we can help to further improve your performance. Please share your experience with software delivery by completing our survey that will be used to foster the next generation of DevOps best practices. To provide ample time for the DevOps community to contribute to this industry wide report we have extended the deadline for the survey until July 2nd.

Thank you to everyone who has participated so far, and the Google Cloud DORA team looks forward to hearing from even more of you soon!

Blog

Speeding Up Digital Transformation with Industry Solutions

2656

Of your peers have already read this article.

2:30 Minutes

The most insightful time you'll spend today!

In this blog, we explore the role of industry-specific solutions in driving digital transformation and discuss how businesses can accelerate their digital transformation journey with the help of these solutions. Keep reading to learn more.

Most large enterprises started with their own data centers and developed in-house solutions to meet their specific business needs, regulations, and industry specifications. These solutions were based on traditional applications from legacy vendors like Oracle and Microsoft — or even mainframes — and from key technology providers like SAP and VMware. During the last decade, organizations started their digital transformation journey by migrating their IT infrastructure, applications, and data to the cloud to reduce operating costs and gain efficiencies as their needs scaled.

The next step in the journey was to take advantage of cloud-based data analytics, services and scalability to drive business growth and revenue. Rather than offer generic “industry clouds” which require multi-year IT deployments and significant customization, Google Cloud has responded to customer needs by developing production-ready industry solutions that address specific use cases with repeatability across organizations.

These industry solutions are grounded in Google Cloud’s differentiated capabilities, including AI, ML, and data analytics. With these, you can dramatically reduce implementation time and realize value from the cloud more quickly with deep insights into your customers and more efficient interactions with your suppliers and partners.

Here are some highlights from the That Digital Show Podcast where Umesh Vemuri, VP of Global Strategic Customers and Industries at Google Cloud, discusses his industry strategy.

Why Google Cloud solutions?

“We are uniquely positioned to help enterprises with solutions based on our deep understanding of customer needs that are supported by our technologies. There are three examples that come to mind.
The first is our understanding of the consumer from the standpoint of running an ecommerce platform. We have the solutions to run digital platforms at a very large scale, including the engineering practices we bring to support organizations during important high traffic events like Black Friday and Cyber Monday.

The second example deals with media and entertainment as a whole. We operate the world’s largest streaming service and support the largest digital platforms currently out there. That means that whatever problems our media customers are experiencing, there’s a good chance we’ve already seen them and know how to deal with them.

Finally, there is our experience with AI and big data. Our leadership in deploying our AI and big data healthcare technologies has given us the experience to solve complex problems — such as techniques to support evidence-based selection, drug therapy, and molecular profiling.”

B to B to C

“Google is a B to B organization, I always like to add that we are also B to B to C, because the concern the consumer ultimately has is their experiences and the journey that they’re on. Connecting the dots between the business and the consumer experience is really critical and a real big differentiator in how we could better serve our customers.

For example, take Ford Motors. Really think about the challenges they have — traditional problems around manufacturing, core I. T. modernization and information, and how to remove costs. But then when you really think about the core of the business, how do you actually make this incredible experience for drivers of Ford vehicles? What do you want to do from an infotainment perspective? What do you want to do in speech-to-text conversion?

And suddenly your business is really a direct-to-consumer experience. Ultimately, all the infrastructure and technology is designed to provide the consumer — who’s ultimately buying that vehicle — with an amazing experience that will maintain their loyalty.

From this example, we can see this kind of linkage in every industry: from retail and e-commerce, media, and direct streaming to healthcare with direct telehealth.”

Solutions that transform the consumer experience

“The consumer’s expectations are constantly shifting and we have to be able to provide the technologies, the structure, and the solutions to our customers to be able to meet those changing expectations at that consumer level.

So first, we want to be very clear on the industry segments that we’re going to focus on and what we believe our clear differentiation will be. So we’ve focussed on ten industries including: retail, financial services, manufacturing, telecommunications, media and entertainment, healthcare and life sciences, education, government, supply chain and logistics and gaming.

Second, we really have to be very prescriptive about the solution pillars in the areas where our customers tell us we have challenges. We want to build solutions that solve not only today’s issues, but the problems of the future.

And third, in those pillars, we have to be very clear on what are the specific use cases that we think have high value for our customers. Then make these available as a catalog of actual products and production-ready solutions that we and our partners in the ecosystem provide.”

Google Cloud industry solutions focus on our top ten industries where we can provide differentiated value to organizations. Whether it’s discovery in retail, AI-enabled call centers, or automotive tools for connected cars, we are delivering production-ready solutions that are ready to implement with minimum customization.

How-to

How to Build A Basic Image Search Utility for Natural Language Queries

4688

Of your peers have already read this article.

6:00 Minutes

The most insightful time you'll spend today!

Read the post to walk through the components required for building a basic image search utility for natural language queries and how learn how the components are connected to each other!

This post shows how to build an image search utility using natural language queries. Our aim is to use different GCP services to demonstrate this. At the core of our project is OpenAI’s CLIP model. It makes use of two encoders – one for images and one for texts. Each encoder is trained to learn representations such that similar images and text embeddings are projected as close as possible.

We will first create a Flask-based REST API capable of handling natural language queries and matching them against relevant images. We will then demonstrate the use of the API through a Flutter-based web and mobile application. Figure 1 shows how our final application would look like:

Figure 1 real
Figure 1: Final application overview.

All the code shown in this post is available as a GitHub repository. Let’s dive in. 

Application at a high-level

Our application will take two queries from the user:

  • Tag or keyword query. This is needed in order to pull a set of images of interest from Pixabay. You can use any other image repositories for this purpose. But we found Pixabay’s API to be easier to work with. We will cache these images to optimize the user experience. Suppose we wanted to find images that are similar to this query: “horses amidst flowers”. For this, we’d first pull in a few “horse” images and then run another utility to find out the images that best match our query.  
  • Longer or semantic query that we will use to retrieve the images from the pool created in the step above. These images should be semantically similar to this query. 

Note: Instead of two queries, we could have only taken a single long query and run named-entity extraction to determine the most likely important keywords to run the initial search with. For this post, we won’t be using this approach. 

Figure 2 below depicts the architecture design of our application and the technical stack used for each of the components.

Figure 2
Figure 2: Architecture design and flow.

Figure 2 also presents the core logic of the API we will develop in bits and pieces in this post. We will deploy this API on a Kubernetes cluster using the Google Kubernetes Engine (GKE). The following presents a brief directory structure of our application code-base:

after figure 2

Next, we will walk through the code and other related components for building our image search API. For various machine learning-related utilities, we will be using PyTorch

Building the backend API with Flask

First, we’d need to fetch a set of images with respect to user-provided tags/keywords before performing the natural language image search. The utility below from the pixabay_utils.py script can do this for us:

  def fetch_images_tag(pixabay_search_keyword, num_images):
    """
    Fetches images from Pixabay w.r.t a keyword.
    :param pixabay_search_keyword: Keyword to perform the search on Pixabay.
    :param num_images: Number of images to retrieve.
    :return: List of PIL images.
    :return: List of image URLs.
    """
    query = (
        PIXABAY_API
        + "&q="
        + pixabay_search_keyword.lower()
        + "&image_type=photo&safesearch=true&per_page="
        + str(num_images)
    )
    
    response = requests.get(query)
    output = response.json()

    all_images = []
    all_image_urls = []

    for each in output["hits"]:
        imageurl = each["webformatURL"]
        response = requests.get(imageurl)
        image = Image.open(BytesIO(response.content)).convert("RGB")
        all_images.append(image)
        all_image_urls.append(imageurl)

    return (all_images, all_image_urls)

Note that all the API utilities are logging relevant information. But for brevity, we have omitted the lines of code responsible for that. Next, we will see how to invoke the CLIP model and select the images that would best match a given query semantically.  For this, we’ll be using Hugging Face, an easy-to-use Python library offering state-of-the-art NLP capabilities. We’ll collate all the logic related to this search inside a SimilarityUtil class:

  class SimilarityUtil:
    def __init__(self):
        self.model = CLIPModel.from_pretrained(CLIP_MODEL)
        self.processor = CLIPProcessor.from_pretrained(CLIP_PREPROCESSOR)
        self.device = "cuda" if torch.cuda.is_available() else "cpu"

    def perform_sim_search(self, images, query_phrase, top_k=3):
        """
        Performs similarity search between the images and query.
        :param images: A list of PIL images initially retrieved with
        respect to some entity e.g. Tiger.
        :param query_phrase: A list containing a single text query,
        e.g. "Tiger drinking water".
        :param top_k: Number of top images to return from `images`.
        :return: Top-k indices matching the query semantically and
        their similarity scores.
        """
        model = self.model.to(self.device)
        # Obtain the text-image similarity scores
        with torch.no_grad():
            inputs = self.processor(
                text=[query_phrase], images=images, return_tensors="pt", padding=True
            )
            inputs = inputs.to(self.device)
            outputs = model(**inputs)

        # Image-text similarity scores
        logits_per_image = outputs.logits_per_image.cpu()
        (top_indices, top_scores) = self.sort_scores(logits_per_image, top_k)

        return (top_indices, top_scores)

    def sort_scores(self, scores, top_k):
        """
        Sorts the scores in a descending manner.
        :param scores: Scores to sort through.
        :param top_k: Number of top scores to return.
        :return: Top-k scores and their indices.
        """
        values, indices = scores.squeeze().topk(top_k)
        top_indices, top_scores = [], []

        for score, index in zip(values, indices):
            top_indices.append(int(index.numpy()))
            score = score.numpy().tolist()
            top_scores.append(round(score, 3))

        return (top_indices, top_scores)

CLIP_MODEL uses a ViT-base model to encode the images for generating meaningful embeddings with respect to the provided query. The text-based query is also encoded using A Transformers-based model for generating the embeddings. These two embeddings are matched with one another during inference. To know more about the particular methods we are using for the CLIP model please refer to this documentation from Hugging Face. 

In the code above, we are first invoking the CLIP model with images and the natural language query. This gives us a vector (logits_per_image) that contains the similarity scores between each of the images and the query. We then sort the vector in a descending manner. Note that we are initializing the CLIP model while instantiating the SimilarityUtil to save us the model loading time. This is the meat of our application and we have tackled it already. If you want to interact with this utility in a live manner you can check out this Colab Notebook

Now, we need to collate our utilities for fetching images from Pixabay and for performing the natural language image search inside a single script – perform_search.py. Following is the main class of that script:

  class Searcher:
    def __init__(self):
        self.similarity_model = SimilarityUtil()

    def get_similar_images(self, keyword, semantic_query, pixabay_max, top_k):
        """
        Finds semantically similar images.
        :param keyword: Keyword to search with on Pixabay.
        :param semantic_query: Query to find semantically similar images retrieved from Pixabay.
        :param pixabay_max: Number of maximum images to retrieve from Pixabay.
        :param top_k: Top-k images to return.
        :return: Tuple of top_k URLs and the similarity scores of the images present inside the URLs.
        """
        images_redis_key = keyword + "_images"
        urls_redis_key = keyword + "_urls"

        if redis_client.exists(images_redis_key) and redis_client.exists(
            urls_redis_key
        ):
            keyword_images = redis_client.get(images_redis_key)
            keyword_image_urls = redis_client.get(urls_redis_key)
        else:
            (keyword_images, keyword_image_urls) = fetch_images_tag(
                keyword, pixabay_max
            )
            redis_client.set(images_redis_key, keyword_images)
            redis_client.set(urls_redis_key, keyword_image_urls)

        (top_indices, top_scores) = self.similarity_model.perform_sim_search(
            keyword_images, semantic_query, top_k
        )

        top_urls = [keyword_image_urls[index] for index in top_indices]

        return (top_urls, top_scores)

Here, we are just calling the utilities we had previously developed to return the URLs of the most similar images and their scores. What is even more important here is the caching capability. For that, we combined GCP’s MemoryStore and a Python library called direct-redis. More on setting up MemoryStore later. 

MemoryStore provides a fully managed and low-cost platform for hosting Redis instances. Redis databases are in memory and light-weight making them an ideal candidate for caching. In the code above, we are caching the images fetched from Pixabay and their URLs. So, in the event of a cache hit, we won’t need to call the CLIP model and this will tremendously improve the response time of our API. 

Other options for caching

We can cache other elements of our application. For example, the natural language query. When searching through the cached entries to determine if it’s a cache hit, we can compare two queries for semantic similarity and return results accordingly. 

Consider that a user had entered the following natural language query: “mountains with dark skies”. After performing the search, we’d cache the embeddings of this query. Now, consider that another user entered another query: “mountains with gloomy ambiance”. We’d compute its embeddings and run a similarity search with the cached embeddings. We’d then compare the similarity scores with respect to a threshold and parse the most similar queries and their corresponding results. In case of a cache miss, we’d just call the image search utilities we developed above. 

When working on real-time applications we often need to consider these different aspects and decide what enhances the user experience and maximizes business at the same time. 

All that’s left now for the backend is our Flask application – main.py:

  @app.route("/search", methods=["GET"])
def get_images():
    tag = request.args.get("t").lower()
    query = request.args.get("s_query").lower()
    top_k = request.args.get("k")

    (top_urls, top_scores) = searcher.get_similar_images(
        tag, query, MAX_PIXABAY_SEARCH, int(top_k)
    )

    return jsonify({"top_urls": top_urls, "top_scores": top_scores})

Here we are first parsing the query parameters from the request payload of our search API.  We are then just calling the appropriate function from perform_search.py to handle the request. This Flask application is also capable of handling CORS. We do this via the flask_cors library:

  cors = CORS(
    app,
    resources={
        r"/search/*": {"origin": "*"},
        r"/test/*": {"origin": "*"},
    },
)

And this is it! Our API is now ready for deployment. 

Deployment with Compute Engine and GKE

The reason why we wanted to deploy our API on Kubernetes is because of the flexibility Kubernetes offers for managing deployments. When operating at scale, auto scalability and load balancing are very important. With the comes the requirement of security — we’d not want to expose the utilities for interacting with any internal services such as databases. With Kubernetes, we can achieve all these easily and efficiently. 

GKE provides secured and fully managed functionalities for operationalizing Kubernetes clusters. Here are the steps to deploy the API on GKE at a glance:

  • We first build a Docker image for our API and then push it to the Google Container Registry (GCR).
  • We then create a Kubernetes cluster on GKE and initialize a deployment.
  • We then add scalability options.
  • If any public exposure is needed for the API, we then tackle it. 

We can assimilate all the above into a shell script – k8s_deploy.sh:

  ## Docker build and push ## 
# We are inside the `server` directory
docker build -t gcr.io/${PROJECT_ID}/search_service .
docker push gcr.io/${PROJECT_ID}/search_service

## Deploy on a GKE cluster ##
# Configure the Docker command-line tool to authenticate to Container Registry
gcloud auth configure-docker

# Create a Kubernetes cluster
gcloud container clusters create image-search-nlp 

# Create a deployment
kubectl create deployment clip-search --image=gcr.io/${PROJECT_ID}/search_service

# Number of worker replicas
kubectl scale deployment clip-search --replicas=3

# HorizontalPodAutoscaler resource
kubectl autoscale deployment clip-search --cpu-percent=80 --min=1 --max=5

# Expose deployment
kubectl  expose deployment clip-search --name=clip-search-service --type=LoadBalancer --port 80 --target-port 8080

These steps are well explained in this tutorial that you might want to refer to for more details. We can configure all the dependencies on our local machine and execute the shell script above. We can also use the GCP Console to execute it since a terminal on the GCP Console is pre-configured with the system-level dependencies we’d need. In reality, the Kubernetes cluster should only be created once and different deployment versions should be created under it. 

After the above shell script is run successfully, we can run kubectl get service to know the external IP address of the service we just deployed:

  NAME                       CLUSTER-IP    EXTERNAL-IP     PORT(S)          AGE
clip-search-service      10.3.251.122    203.0.113.0     80:30877/TCP     10s

We can now consume this API with the following base URI: http://203.0.113.0/. If we wanted to deal with only http-based API requests, then we are done here. But secured communication is often a requirement in order for applications to operate reliably. In the following section, we are to discuss how to configure the additional items to allow our Kubernetes cluster to allow https requests.  

Configurations for handling https requests with GKE

A secure connection is almost often a  must-have requirement in modern client/server applications. The front-end Flutter application would be hosted on GitHub Pages for this project, and it requires https-based connection as well. Even if configuring https connection particularly for a GKE-based cluster can be considered a chore, its setup might seem daunting at first.

There are six steps to configure https connection in the GKE environment: 

  1. You need to have a domain name, and there are a lot of inexpensive options that you can buy. For instance, mlgde.com domain for this project is acquired via Gabia which is a Korean service provider.
  2. A reserved (static) external IP address has to be acquired via gcloud command or GCP console
  3. You need to bind the domain name with the acquired external IP address. This is a platform-specific configuration that issued the domain name to you. 
  4. There is a special ManagedCertificate resource which is specific to the GKE environment. ManagedCertificate resource specifies the domain that the SSL certificate will be created for, so you need this. 
  5. An Ingress resource should be created by listing the static external IP address, ManagedCertificate resource, and the service name and port which the incoming traffic will be routed to. The Service resource could remain the same as in the above section with only changes from LoadBalancer to ClusterIP. 
  6. Last but not least, you need to modify the existing Flask application and Deployment resource to support liveness and readiness probes which are used to check the health status of the Deployment. The Flask application side can be simply modified with the flask-healthz Python package, and you only need to add livenessProbe and readinessProbe sections in the Deployment resource. In the code example below, the livenessProbe and readinessProbe are checked via /alive and /ready endpoints respectively.
  from flask_healthz import healthz
from flask_healthz import HealthError


app = Flask(__name__)
app.register_blueprint(healthz, url_prefix="/")


def printok():
   print("Everything is fine")


def liveness():
   try:
       printok()
   except Exception:
       raise HealthError("Can't connect to the file")


def readiness():
   try:
       printok()
   except Exception:
       raise HealthError("Can't connect to the file")


app.config.update(
   HEALTHZ = {
       "alive": "main.liveness",
       "ready": "main.readiness",
   }
)

One thing to be careful of is the initialDelaySeconds attribute of the probes. It is uncommon to configure this attribute with a big number, but it could be bigger than 90 – 120 seconds depending on the size of the model to be used. For this project, it is configured in 90 seconds in order to wait until the CLIP model is fully loaded into memory (full YAML script here).

  livenessProbe:
 httpGet:
   path: /alive
   port: 8080
 initialDelaySeconds: 90
 periodSeconds: 10

readinessProbe:
 httpGet:
   path: /ready
   port: 8080
 initialDelaySeconds: 90
 periodSeconds: 10

Again, these steps may seem daunting at first, but it will become clear when you have done it once. Here is the official document for Using Google-managed SSL certificates You can find all the GKE-related resources used in this project here

Once every step is completed you should be able to see your server application running on the GKE environment. Please make sure to run kubectl apply command whenever you create Kubernetes resources such as Deployment, Service, Ingress, and ManagedCertificate, and it is important to wait for more than 10 minutes until the ManagedCertifcate provisioning is done. 

You can run gcloud compute addresses list command to find out the static external IP address that you have configured.

  NAME  ADDRESS/RANGE  TYPE      PURPOSE  NETWORK  REGION  SUBNET  STATUS
gde      34.149.231.34       EXTERNAL                                                                    IN_USE

Then, the IP address has to be mapped to the domain. Figure 3 is a screenshot of a dashboard from where we got the mlgde.com domain. It clearly shows mlgde.com is mapped to the static external IP address configured in GCP.

Figure 3
Figure 3: API endpoints mapped to our custom domain.

In case you’re wondering why we didn’t deploy this application on App Engine, well that is because of the compute needed to execute the CLIP model. App Engine instance won’t fit in that regime. We could have also incorporated compute-heavy capabilities via a VPC Connector. That is a design choice that you and your team would need to consider. In our experiments, we found the GKE deployment to be easier and suitable for our needs. 

Infrastructure for the CLIP model

As mentioned earlier, at the core of our application is the CLIP model. It is computationally a bit more expensive than the regular deep learning models. This is why it makes sense to have the hardware infrastructure set up accordingly to execute it. We ran a small benchmark in order to see how a GPU-based environment could be beneficial here. 

We ran the CLIP on a Tesla P100-based machine and also on a standard CPU-only machine 1000 times. The code snippet below is the meat of what we executed:

  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"

start_time = time.time()
for _ in range(1000):
    with torch.no_grad():
        model = model.to(DEVICE)
        inputs = processor(text=[semantic_search_phrase], 
                        images=all_images, return_tensors="pt", padding=True)
        inputs = inputs.to(DEVICE)
        outputs = model(**inputs)
end_time = time.time() - start_time
print(f"Total time: {end_time:.3f} seconds.")

As somewhat expected, with the GPU, the code took 13 minutes to complete execution. With no GPU, it took about 157 minutes.

It is uncommon to leverage GPUs for model prediction because of cost restrictions, but sometimes we have to access GPUs for deploying a big model like CLIP. We configured a GPU-based cluster on GKE and compared the performance differences with and without it. It took about 1 second to handle a request with GPU and MemoryStore cache while it took more than 4 seconds with MemoryStore only (without the GPUs). 

For the purposes of this post, we used a CPU-based cluster on Kubernetes. But It is easy to configure GPU usage in a GKE cluster. This document shows you how to do so. For a short summary, there are two steps. First, a node should be configured with GPUs when creating a GKE cluster. Second, GPU drivers should be installed in GKE nodes. You don’t need to visit and manually install GPU drivers for each node by yourself. Rather you can simply apply the DaemonSet resource to GKE as described here.

Setting up MemoryStore

In this project, we first query the general concept of images to Pixabay, then we filter the images with a semantic query using CLIP. It means we can cache the initially retrieved images from Pixabay for the next specific semantic query. For instance, you may want to search with “gentleman wearing tie” at first, then you may want to retry searching for “gentleman wearing glass”. In this case, the base images remain all the same, so they could be stored in a cache server like Redis. 

MemoryStore is a GCP service wrapping the Redis which is an in-memory data store, so you can simply use a standard Redis Python package for accessing it. The only thing to be careful about when provisioning a MemoryStore Redis instance is to make sure it is in the same region where your GKE cluster or Compute Engine instance is.

Figure 4
Figure 4: MemoryStore setup.

The code snippet below shows how to make a connection to the Redis instance in Python. Nothing specific to GCP, but you only need to be aware of the usage of the standard redis-py package

  # REDISHOST is the IP address to the MemoryStore instance
redis_host = os.environ.get("REDISHOST", "localhost")
redis_port = int(os.environ.get("REDISPORT", 6379))
redis_client = redis.StrictRedis(host=redis_host, port=redis_port)

After creating a connection, you can store and retrieve data from MemoryStore. There are more advanced use cases of Redis, but we only used exists, get, and set methods for the demonstration purpose. These methods should be very familiar if you know maps, dictionaries, or other similar data structures. For the code portion that uses Redis-related utilities, please refer to the Searcher Python class we discussed in an earlier section. 

In the URLs below, you can find side-by-side comparisons of using MemoryStore:

Putting everything together

All that’s left now is to collate the different components we developed in the sections above and deploy our application with a frontend. All the frontend-related code is present here

  • The front-end application is written in the Flutter development kit. The main screen contains two text fields for queries to Pixabay and CLIP model respectively. When you click the “Send Query” button, it will send out a RestAPI request to the server. After receiving the result back from the server, the retrieved images from the semantic query will be displayed at the bottom section of the screen. 
    • Please note that a Flutter application can be deployed to various environments including desktop, web, iOS, and Android. In order to keep as simple as possible, we chose to deploy the application to the GitHub Pages. Whenever there is any change to a client-side source directory, the GitHub Action will be triggered to build a web page and deploy the latest version to the GitHub Pages. 

Our final application is deployed here and it looks like so:

Figure 1
Figure 5: Live application screen.

Note that due to constraints, the above-mentioned URL will only be live for one or two months.  

It is also possible to redeploy the back-end application with a GitHub Action. 

  • The very first step is to craft a Dockerfile like below. Since Python is a scripting language, and there are lots of heavy packages that the application is dependent on, it is important to cache the steps. For instance, installing the dependencies should be separated from other commands.
  FROM pytorch/pytorch:latest
WORKDIR /app

# install the dependencies
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

COPY . .  

# set up environment variables
ENV PIXABAY_API_KEY="..."
ENV REDIS_IN_USE="true"
ENV REDISHOST="..."

# expose port that Flask app is listening on
EXPOSE 8080

# run the Flask app
CMD [ "python3", "main.py" ]
  • With the Dockerfile defined, we can use a GitHub Action like this for automatic deployment. 

Edge cases

Since the CLIP model is pre-trained on a large corpus of image and text pairs it’s likely that it may not generalize well to every natural language query we throw at it. Also, because we are limiting the number of images on which the CLIP model can operate, this somehow restricts the expressivity of the model.

We may be able to improve the performance for the second situation by increasing the number of images to be pre-fetched and by indexing them into a low-cost and high-performance database like Datastore

Costs

In this section, we wanted to provide the readers a breakdown of the costs they might incur in order to consume the various services used throughout the application. 

  • Frontend hosting
    • The front-end application is hosted on GitHub Pages, so there is no expenditure for this.
  • Compute Engine
    • With an e2-standard-2 instance type without GPUs, the cost is around $48.92 per month. In case you want to add a GPU (NVIDIA K80), the cost goes up to $229.95 per month.
  • MemoryStore
    • The cost for MemoryStore depends on the size. With 1GB of space, the cost is around $35.77 per month, and whenever you add more GBs the cost will be doubled.
  • Google Kubernetes Engine
    • The monthly cost for a 3 node GKE cluster with n2-standard-2 (vCPUs: 2, RAM: 8GB without GPUs) is about $170.19. If you add one GPU (NVIDIA K80) to the cluster, the cost goes up to $835.48.

While you may think that is a lot cost-wise, it is good to know that Google gives away free $300 credits when you create a new GCP account. It is still not enough for leveraging GPUs, but it is enough to learn and experiment with GKE and MemoryStore usage.

Conclusion

In this post, we walked through the components needed to build a basic image search utility for natural language queries. We discussed how these different components are connected to each other. Our image search API is able to utilize caching and was deployed on a Kubernetes cluster using GKE. These elements are essential when building a similar service to cater to a much bigger workload. We hope this post will serve as a good starting point for that purpose. Below are some references on similar areas of work that you can explore:

Acknowledgments: We are grateful to the Google Developers Experts program for supporting us with GCP credits. Thanks to Karl Weinmeister and Soonson Kwon of Google for reviewing the initial draft of this post. 

3187

Of your peers have already watched this video.

1:30 Minutes

The most insightful time you'll spend today!

Explainer

Start Your Serverless Expeditions Now!

Google Cloud’s fully managed serverless platform like Cloud Run helps build and run highly scalable containerized applications. In traditional scenarios, over or under-provisioning enterprise applications can result in outages and cost hurdles. Severless Experts at the Google Cloud succinctly breakdown what serverless means for an organization and how Engineering Managers and CTO can rest assured with the predictability, developer productivity, automated release process and infrastructure abstraction.

Watch the video to unravel the serverless journey with Cloud Run!

6532

Of your peers have already watched this video.

24:00 Minutes

The most insightful time you'll spend today!

Webinar

Swarovski’s Journey towards Online and Offline Conversion with Predictive Analytics

Luxury brand and leader in crystals and glass production, Swarovski has charmed customers with its exquisite collections for over 125 years. To understand their customers better and map their online behaviors, Swarovski had to overcome prediction hurdles as majority of the purchases are not frequent or habitual. They are mostly impulse buys or have no rational behind the purchase in order for the brand to accurately map customers’ interest and delight them with relevant personalization or website customization strategy.

Swarovski used a machine learning (ML) model to predict the most performing SKUs and list of products based on both online and offline indicators to target buyers. A score was assigned to each product in the list and was personalized at the country level that delivered relevant insights. Swarovski is aiming to expand the product listing page to personalize at customer level. Watch the video to dive deep into Swarovski’s data analytics efforts to answer complex questions, reporting and prediction using both online and offline data.

3754

Of your peers have already watched this video.

38:00 Minutes

The most insightful time you'll spend today!

How-to

Microservices in the Cloud with Kubernetes and Istio

Are you building or interested in building microservices? They are a powerful method to build a scalable and agile backend, but managing these services can feel daunting: building, deploying, service discovery, load balancing, routing, tracing, auth, graceful failures, rate limits, and more.

The most suited solution for you is Istio. Istio is built with containers and microservices management in mind. The Apigee Edge API platform provides common visibility and management across both APIs and microservices for organizations of any size.

For instance, within a single Kubernetes cluster—and even with Istio helping mediate—an unreliable or slow microservice can drag the SLA of an entire application down along with it.

The kinds of sophisticated analytics that the Apigee platform provides can help administrators and product managers see these kinds of issues and react to them before it’s too late. Apigee is used by many organizations to enforce various types of quotas, allowing API teams to dynamically adjust how much API load is consumed by each organization who uses an API. This session will show you how the Kubernetes container management system and Istio service mesh can simplify many of the operational challenges of microservices, including an in-depth live demo.

More Relevant Stories for Your Company

Whitepaper

How Google Anthos Can Help Modernize Application Security

Anthos is a modern app management platform from Google Cloud that aims to deliver a consistent development, operations, and security experience across cloud environments. Anthos is designed for enterprise organizations that want to accelerate the development and deployment of dynamic apps and who value service automation, cost governance, and security

Blog

Three Reasons Why Enterprises Must Think Next-gen Serverless

As we reflect on the past year, Heraclitus' phrase “The only constant in life is change” has never rang more true. With the pandemic, companies had to shift operations, launch new products and adapt to extreme demand patterns, sometimes within a matter of weeks. To respond to customer needs faster

Case Study

Target Leverages Google Cloud to Create Market-defining Online Experience

In the hyper-competitive world of online retail sales, ease-of-use and transaction speed can make or break business outcomes. However, a few years ago US Retail giant Target was going through a period of uncertainty. While the company had over 1800 stores across the US with an estimated 85% of US

Blog

Google Cloud Offering a Natural Migration Path for Developers Accustomed to Heroku

Modern developers worldwide have grown accustomed to the comfort of writing code, pushing to a remote Git repository and having that code be deployed at an accessible URL without having to worry about how it is deployed. This was a workflow popularized by Heroku years ago which brought joy and

SHOW MORE STORIES