<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem:  Sanket Sudake</title>
    <description>The latest articles on Forem by  Sanket Sudake (@sanketsudake).</description>
    <link>https://forem.com/sanketsudake</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F383793%2F0e398e98-2224-4b29-9ffb-cbc09ff87787.jpeg</url>
      <title>Forem:  Sanket Sudake</title>
      <link>https://forem.com/sanketsudake</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sanketsudake"/>
    <language>en</language>
    <item>
      <title>Retrieval-Augmented Generation: Using your Data with LLMs</title>
      <dc:creator> Sanket Sudake</dc:creator>
      <pubDate>Thu, 18 Apr 2024 05:43:12 +0000</pubDate>
      <link>https://forem.com/infracloud/retrieval-augmented-generation-using-your-data-with-llms-1l7d</link>
      <guid>https://forem.com/infracloud/retrieval-augmented-generation-using-your-data-with-llms-1l7d</guid>
      <description>&lt;p&gt;Large Language Models (LLM) are great at answering questions based on which they have been trained on, mostly content available in the public domain. However, most enterprises want to use the LLMs with their specific data. Methods like LLM finetuning, RAG, and fitting data into the prompt context are different ways to achieve this.  &lt;/p&gt;

&lt;p&gt;This article explains the basics of Retrieval-Augmented Generation (RAG) and demonstrates how your data can be used with LLM-backed applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Retrieval Augmented Generation (RAG)
&lt;/h2&gt;

&lt;p&gt;Retrieval-Augmented Generation (RAG) involves retrieving specific data chunks from an indexed dataset and using a Large Language Model (LLM) to generate an answer to a given question or task. This process typically consists of two main components at a high level:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Retriever&lt;/strong&gt;: This component retrieves relevant data for the user-provided query.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generator&lt;/strong&gt;: The generator performs an augmentation process on retrieved data (usually by putting data in prompt context) and feeds data to the LLM, to generate a relevant response.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.infracloud.io%2Fassets%2Fimg%2FBlog%2Fretrieval-augmented-generation-using-data-with-llms%2Fhigh-level-rag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.infracloud.io%2Fassets%2Fimg%2FBlog%2Fretrieval-augmented-generation-using-data-with-llms%2Fhigh-level-rag.png" alt="High-level RAG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;(High-level RAG)&lt;/center&gt;

&lt;h2&gt;
  
  
  SkillScout - Implementing Retrieval Augmented Generation (RAG)
&lt;/h2&gt;

&lt;p&gt;While the above explanation gives a very high-level overview of the RAG, below we take an example of RAG implementation for the case internally explored at InfraCloud.  &lt;/p&gt;

&lt;p&gt;It started with an internal ask from talent management team,  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Team, as of today, when we are looking for a specific skills for a customer from our talent, we mostly scan through updated resumes or try to match based on our past memories, if a person has certain skillset. This is not very efficient.&lt;br&gt;&lt;br&gt;
We can explore, if we can leverage LLM to help us query our resume dataset better.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's say we have a dataset of resumes/CVs of candidates from an organization and the talent search/management team is looking to extract valuable insights from the dataset via a ChatGPT kind of interface through Question-Answering. We are giving a nickname to our solution, “SkillScout”.&lt;/p&gt;

&lt;p&gt;Samples prompts/questions we are expecting from users of the solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Show me candidate skilled in {skill}”&lt;/li&gt;
&lt;li&gt;“Show me candidates with {certification name} certification”&lt;/li&gt;
&lt;li&gt;“Find resume with {x-y} years of experience”&lt;/li&gt;
&lt;li&gt;“What are the skills of {candidate} ?”&lt;/li&gt;
&lt;li&gt;“How much experience does {candidate} have?”&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;This section gives a brief overview of different components within our solution and data flow amongst them. &lt;/p&gt;

&lt;p&gt;We use &lt;a href="https://python.langchain.com/docs/get_started/introduction" rel="noopener noreferrer"&gt;langchain&lt;/a&gt; and &lt;a href="https://platform.openai.com/docs/guides/text-generation" rel="noopener noreferrer"&gt;OpenAI text generation&lt;/a&gt; APIs for implementation, but most of the parts explained in the below pipelines are customizable. You can refer to the source from &lt;a href="https://github.com/infracloudio/skillscout/tree/main" rel="noopener noreferrer"&gt;SkillScout GitHub Repo&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Eg. LLM or Embeddings model could be swapped with any compatible implementation, as you can notice from &lt;a href="https://github.com/infracloudio/skillscout/tree/main/core" rel="noopener noreferrer"&gt;the core package&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;We have three pipelines at a high level:&lt;/p&gt;
&lt;h4&gt;
  
  
  Document Preprocessing pipeline
&lt;/h4&gt;

&lt;p&gt;This pipeline handles the extraction of specific details from resumes in various PDF formats. Given the diverse structures of resumes, this step is crucial for retrieving relevant information based on user queries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.infracloud.io%2Fassets%2Fimg%2FBlog%2Fretrieval-augmented-generation-using-data-with-llms%2Fdocument-preprocessing-pipeline.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.infracloud.io%2Fassets%2Fimg%2FBlog%2Fretrieval-augmented-generation-using-data-with-llms%2Fdocument-preprocessing-pipeline.png" alt="Document Preprocessing Pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;(Document Preprocessing Pipeline)&lt;/center&gt;

&lt;p&gt;The summary prompt below is sent to LLM along with resume data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please extract the following data from the resume text provided in
triple quotes below and provide them only in format specified:

Name of the candidate:
Professional Summary:
Total years of experience:
Skills (comma separated):
Companies worked for (comma separated):
Education:
Certifications (comma separated):

When extracting the candidate’s total years of experience if available
in the resume text or calculate the total years of experience based on
the dates provided in the resume text.

If you are calculating then assume current month and year as Jan 2024.

Resume Text:
{text}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Vector Store Ingestion pipeline
&lt;/h4&gt;

&lt;p&gt;Once the resumes are processed and summarized, this pipeline stores and indexes all the resume data with a vector store. This ensures the information is readily available and easily accessible for the Retrieval-Augmented Generation (RAG) process.&lt;br&gt;&lt;br&gt;
We use “sentence-transformers” encodings for our pipeline, but &lt;a href="https://huggingface.co/spaces/mteb/leaderboard" rel="noopener noreferrer"&gt;the MTEB leaderboard&lt;/a&gt; is a good source to compare different embedding models.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.infracloud.io%2Fassets%2Fimg%2FBlog%2Fretrieval-augmented-generation-using-data-with-llms%2Fvector-store-ingestion-pipeline.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.infracloud.io%2Fassets%2Fimg%2FBlog%2Fretrieval-augmented-generation-using-data-with-llms%2Fvector-store-ingestion-pipeline.png" alt="Vector Store Ingestion Pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;(Vector Store Ingestion Pipeline)&lt;/center&gt;
&lt;h4&gt;
  
  
  Retrieval Augmented Generation pipeline
&lt;/h4&gt;

&lt;p&gt;When a new user query arrives, the query undergoes a formatting phase, where it is restructured based on past chat history and previous questions. This step ensures that the query is not only understandable but also aligns with the context of the ongoing conversation.  &lt;/p&gt;

&lt;p&gt;Next, the reformatted query is fed into our LLM embeddings model to calculate its embedding. This process converts the query into an embedded query.  &lt;/p&gt;

&lt;p&gt;With the query now embedded, we move on to a pivotal step: the vector similarity search operation. Here, we compare the embedded query against a vector store containing relevant information. This search with retriever enables us to retrieve highly relevant and contextually appropriate data, setting the stage for a more informed response.  &lt;/p&gt;

&lt;p&gt;Armed with the retrieved information, we construct a prompt tailored to the LLM model, enriching it with the contextual data gleaned from the vector search. This custom prompt is then presented to the LLM, which leverages it to generate responses that are not just accurate but also deeply contextualized to the user's query and the ongoing conversation.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.infracloud.io%2Fassets%2Fimg%2FBlog%2Fretrieval-augmented-generation-using-data-with-llms%2Fretrieval-augmented-generation-pipeline.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.infracloud.io%2Fassets%2Fimg%2FBlog%2Fretrieval-augmented-generation-using-data-with-llms%2Fretrieval-augmented-generation-pipeline.png" alt="Retrieval Augmented Generation Pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;(Retrieval Augmented Generation Pipeline)&lt;/center&gt;

&lt;p&gt;Based on chat history and query from a user, we first check if we should reformat the question and reduce its dependency on the chat history.  &lt;/p&gt;

&lt;p&gt;Let's say we have two questions,&lt;br&gt;&lt;br&gt;
Query 1: What skills does John Doe have?&lt;br&gt;&lt;br&gt;
Query 2: What's his total years of experience?  &lt;/p&gt;

&lt;p&gt;Now in Query 2, &lt;strong&gt;&lt;em&gt;“his”&lt;/em&gt;&lt;/strong&gt; is a possessive pronoun which refers to John Doe.  We may rewrite Query 2 as “What’s John Doe’s total years of experience?”  &lt;/p&gt;

&lt;p&gt;This helps in embedding contextual information, such as chat history, into the query,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chat History:
{chat_history}

Question: {question}

Given a chat history and the latest user question which might
reference context in the chat history, formulate a standalone question
which can be understood without the chat history.

Do NOT answer the question, just reformulate it if needed and
otherwise return it as is.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generation with retrieved content from the vector store is done via the following prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Context has resume data of candidates. 
Answer the question only based on the following context.
If you don't know the answer, just say that you don't know.
Be concise.

Context: {context}
Question: {question}
Answer:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  SkillScout demo
&lt;/h3&gt;

&lt;p&gt;We load our minimal Resume data as mentioned in &lt;a href="https://github.com/infracloudio/skillscout" rel="noopener noreferrer"&gt;SkillScout project README&lt;/a&gt;.  After generating a summary of resumes and loading data in the vector store, we can see the chat interface via the app command.  &lt;/p&gt;

&lt;p&gt;You can see in the screenshot below that we ask about a particular candidate's experience and skill set in the following question. We also ask people with certain experience. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.infracloud.io%2Fassets%2Fimg%2FBlog%2Fretrieval-augmented-generation-using-data-with-llms%2Fskillscout-resume-chatbot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.infracloud.io%2Fassets%2Fimg%2FBlog%2Fretrieval-augmented-generation-using-data-with-llms%2Fskillscout-resume-chatbot.png" alt="SkillScout resume chatbot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Enhancing RAG Implementation for production applications
&lt;/h2&gt;

&lt;p&gt;One of the key reasons behind RAG's popularity among application developers is its relatively lower barrier to entry compared to directly working with LLMs. With a background in application development, one can easily get started with RAG. Additionally, RAG allows developers to experiment with different foundational or customized LLMs and compare the results, offering flexibility and exploration.  &lt;/p&gt;

&lt;p&gt;However, RAG implementation could be nuanced and complex, depending on factors such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accuracy expectations&lt;/strong&gt;: The level of accuracy required for the task at hand will influence the design and implementation of the RAG system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hallucination prevention&lt;/strong&gt;: Ensuring the generated responses are accurate and relevant, without introducing false or misleading information, is crucial.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dataset scale and nature&lt;/strong&gt;: The dataset's size and nature will impact the retrieval process and the overall performance of the RAG system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the above implementation demonstrates the feasibility of the RAG approach, several considerations are crucial for deploying RAG in production applications.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Factors for Retrieved Chunks in RAG:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Relevance&lt;/strong&gt;: Chunks should be highly relevant to the query or context, ensuring that generated responses are on-topic and useful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diversity&lt;/strong&gt;: Chunks should be diverse, avoiding redundancy and providing a broad range of information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contextuality&lt;/strong&gt;: Chunks should be contextual, considering the conversation history for coherent responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accuracy&lt;/strong&gt;: Ensure retrieved information is accurate and factually correct to prevent incorrect distribution of facts across chunks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ranking&lt;/strong&gt;: The order of retrieved chunks matters; re-ranking steps post-retrieval and incorporating user feedback improves relevance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Optimizing the RAG Pipeline:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Optimizing the RAG pipeline is essential for generating better and more relevant responses. Considerations include:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy and security&lt;/strong&gt;: Ensure personal and sensitive information is not revealed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data management policies&lt;/strong&gt;: Adhere to data management policies, including forgetting past data and injecting fresh data as per requirements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability, reliability, and cost-efficiency&lt;/strong&gt;: Ensure the RAG solution is scalable, reliable, and cost-efficient for enterprise usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Addressing these considerations can optimize RAG implementations for production applications, providing users with accurate, diverse, and contextually relevant responses while maintaining privacy and security.  &lt;/p&gt;

&lt;p&gt;What are other datasets where you can consider using the RAG technique?&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Dataset&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Doc QA&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A chatbot can answer questions based on product documentation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Medical QA&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;We can have a bot answering questions about different medicines based on actual manuals, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Product QA&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Product buyers/consumers can ask questions about the product info and any additional information.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Comparing RAG and LLM finetuning
&lt;/h2&gt;

&lt;p&gt;When it comes to integrating your data with LLMs, two prominent methods stand out: LLM finetuning and Retrieval-Augmented Generation (RAG). Each approach has its own advantages and drawbacks, and ongoing developments continuously enhance their efficacy.&lt;br&gt;&lt;br&gt;
In a practical solution, you may use a &lt;strong&gt;combination&lt;/strong&gt; of both to get better results.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;LLM Finetuning&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;RAG&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Alters LLM&lt;/td&gt;
&lt;td&gt;No alterations to LLM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Less adaptability/flexibility&lt;/td&gt;
&lt;td&gt;More adaptability/flexibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tightly coupled with LLM&lt;/td&gt;
&lt;td&gt;There is no tight dependency on LLM, the model can be swapped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data set size constraints overall considering the cost of finetuning&lt;/td&gt;
&lt;td&gt;No data restrictions as such, cost marginally increases with dataset size increase&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, Retrieval-Augmented Generation (RAG) represents a powerful approach to leveraging Large Language Models (LLMs) for tasks requiring contextual understanding and data retrieval.  &lt;/p&gt;

&lt;p&gt;RAG enables more accurate and contextually relevant responses, making it particularly useful for applications that provide tailored responses to user's queries by extracting information.  &lt;/p&gt;

&lt;p&gt;As advancements in GenAI technology continue, we can expect RAG to play an increasingly important role in enabling more intelligent and context-aware interactions with data. You can follow this article to train LLM-backed applications on your data with RAG; however, having an efficient, scalable cloud infrastructure for AI application building is crucial. For that, you can bring in &lt;a href="https://www.infracloud.io/build-ai-cloud/" rel="noopener noreferrer"&gt;AI &amp;amp; GPU Cloud experts&lt;/a&gt; onboard to help you out.  &lt;/p&gt;

&lt;p&gt;We hope you found this post informative and engaging. For more posts like this one, subscribe to our weekly newsletter. We’d love to hear your thoughts on this post, so do start a conversation on &lt;a href="https://www.linkedin.com/in/sanketsudake/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; :)&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2005.11401" rel="noopener noreferrer"&gt;Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2004.04906" rel="noopener noreferrer"&gt;Dense Passage Retrieval for Open-Domain Question Answering&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>vectordatabase</category>
      <category>llm</category>
    </item>
    <item>
      <title>Using CoreDNS Effectively with Kubernetes
</title>
      <dc:creator> Sanket Sudake</dc:creator>
      <pubDate>Sat, 08 May 2021 14:56:54 +0000</pubDate>
      <link>https://forem.com/infracloud/using-coredns-effectively-with-kubernetes-1mcl</link>
      <guid>https://forem.com/infracloud/using-coredns-effectively-with-kubernetes-1mcl</guid>
      <description>&lt;h3&gt;
  
  
  Backstory
&lt;/h3&gt;

&lt;p&gt;We were increasing HTTP requests for one of our applications, hosted on the Kubernetes cluster, which resulted in a spike of 5xx errors.&lt;br&gt;
The application is a GraphQL server calling a lot of external APIs and then returning an aggregated response.&lt;br&gt;
Our initial response was to increase the number of replicas for the application to see if it improves the performance and reduces errors.&lt;br&gt;
As we drilled down further with the application developer, found most of the failures related to DNS resolution.&lt;br&gt;
That’s where we started drilling down DNS resolution in Kubernetes.&lt;/p&gt;

&lt;p&gt;This post highlights our learnings related to CoreDNS, as we did deep dive in process of troubleshooting.&lt;/p&gt;
&lt;h3&gt;
  
  
  CoreDNS Metrics
&lt;/h3&gt;

&lt;p&gt;DNS server stores record in its database and answers domain name query using the database.&lt;br&gt;
If the DNS server doesn’t have this data, it tries to find for a solution from other DNS servers.&lt;/p&gt;

&lt;p&gt;CoreDNS became the &lt;a href="https://kubernetes.io/blog/2018/12/03/kubernetes-1-13-release-announcement/#coredns-is-now-the-default-dns-server-for-kubernetes"&gt;default DNS service&lt;/a&gt; for Kubernetes 1.13+ onwards.&lt;br&gt;
Nowadays, when you are using a managed Kubernetes cluster or you are self-managing a cluster for your application workloads, you often focus on tweaking your application but not much on the services provided by Kubernetes or how you are leveraging them.&lt;br&gt;
DNS resolution is the basic requirement of any application so you need to ensure it’s working properly.&lt;br&gt;
We would suggest looking at &lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/dns-debugging-resolution/"&gt;dns-debugging-resolution&lt;/a&gt; troubleshooting guide and ensure your CoreDNS is configured and running properly.&lt;/p&gt;

&lt;p&gt;By default, when you provision a cluster you should always have a dashboard to observe for key CoreDNS metrics.&lt;br&gt;
For getting CoreDNS metrics you should have &lt;a href="https://coredns.io/plugins/metrics/"&gt;Prometheus plugin&lt;/a&gt; enabled as part of the CoreDNS config.&lt;/p&gt;

&lt;p&gt;Below sample config using &lt;code&gt;prometheus&lt;/code&gt; plugin to enable metrics collection from CoreDNS instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.:53 {
    errors
    health
    kubernetes cluster.local in-addr.arpa ip6.arpa {
      pods verified
      fallthrough in-addr.arpa ip6.arpa
    }
    prometheus :9153
    forward . /etc/resolv.conf
    cache 30
    loop
    reload
    loadbalance
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following are the key metrics, we would suggest to have in your dashboard.&lt;br&gt;
If you are using Prometheus, DataDog, Kibana etc, you may find ready to use dashboard template from community/provider.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache Hit percentage: Percentage of requests responded using CoreDNS cache&lt;/li&gt;
&lt;li&gt;DNS requests latency

&lt;ul&gt;
&lt;li&gt;CoreDNS: Time taken by CoreDNS to process DNS request&lt;/li&gt;
&lt;li&gt;Upstream server: Time taken to process DNS request forwarded to upstream&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Number of requests forwarded to upstream servers&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6"&gt;Error codes&lt;/a&gt; for requests

&lt;ul&gt;
&lt;li&gt;NXDomain: Non-Existent Domain&lt;/li&gt;
&lt;li&gt;FormErr: Format Error in DNS request&lt;/li&gt;
&lt;li&gt;ServFail: Server Failure&lt;/li&gt;
&lt;li&gt;NoError: No Error, successfully processed request&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CoreDNS resource usage: Different resources consumed by server such as memory, CPU etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We were using DataDog for specific application monitoring. Following is just a sample dashboard I built with DataDog for my analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OqqePNLD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etbh6bha1r74znwjmyae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OqqePNLD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etbh6bha1r74znwjmyae.png" alt="DataDog CoreDNS dashboard"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Reducing DNS Errors
&lt;/h3&gt;

&lt;p&gt;As we started drilling down more into how the application is making requests to CoreDNS, we observed most of the outbound requests happening through the application to an external API server.&lt;/p&gt;

&lt;p&gt;This is typically how resolv.conf looks in the application deployment pod.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nameserver 10.100.0.10
search kube-namespace.svc.cluster.local svc.cluster.local cluster.local us-west-2.compute.internal
options ndots:5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you understand how Kubernetes tries to resolve an FQDN, it tries to DNS lookup at different levels.&lt;/p&gt;

&lt;p&gt;Considering the above DNS config, when the DNS resolver sends a query to the CoreDNS server, it tries to search the domain considering the search path.&lt;/p&gt;

&lt;p&gt;If we are looking for a domain boktube.io, it would make the following queries and it receives a successful response in the last query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;botkube.io.kube-namespace.svc.cluster.local  &amp;lt;= NXDomain
botkube.io.svc.cluster.local &amp;lt;= NXDomain
boktube.io.cluster.local &amp;lt;= NXDomain
botkube.io.us-west-2.compute.internal &amp;lt;= NXDomain
botkube.io &amp;lt;= NoERROR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we were making too many external lookups, we were getting a lot of NXDomain responses for DNS searches.&lt;br&gt;
To optimize this we customized &lt;code&gt;spec.template.spec.dnsConfig&lt;/code&gt; in the Deployment object.&lt;br&gt;
This is how change looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;     &lt;span class="na"&gt;dnsPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterFirst&lt;/span&gt;
     &lt;span class="na"&gt;dnsConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ndots&lt;/span&gt;
         &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above change, resolve.conf on pods changed.&lt;br&gt;
The search was being performed only for an external domain.&lt;br&gt;
This reduced number of queries to DNS servers.&lt;br&gt;
This also helped in reducing 5xx errors for an application.&lt;br&gt;
You can notice the difference in the NXDomain response count in the following graph.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oph6EfYE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zmx156sjhscebauvk1ml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oph6EfYE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zmx156sjhscebauvk1ml.png" alt="CoreDNS Rcode NxDomain Reduction"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A better solution for this problem is &lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/"&gt;Node Level Cache&lt;/a&gt; which is introduced Kubernetes 1.18+.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customizing CoreDNS to your needs
&lt;/h3&gt;

&lt;p&gt;We can customize CoreDNS by using plugins.&lt;br&gt;
Kubernetes supports a different kind of workload and the standard CoreDNS config may not fit all your needs.&lt;br&gt;
CoreDNS has a couple of in-tree and external plugins.&lt;br&gt;
Depending on the kind of workloads you are running on your cluster, let’s say applications intercommunicating with each other or standalone apps that are interacting outside your Kubernetes cluster, the kind of FQDN you are trying to resolve might vary.&lt;br&gt;
We should try to adjust the knobs of CoreDNS accordingly.&lt;br&gt;
Suppose you are running Kubernetes in a particular public/private cloud and most of the DNS backed applications are in the same cloud.&lt;br&gt;
In that case, CoreDNS also provides particular cloud-related or generic plugins which can be used to extend DNS zone records.&lt;/p&gt;

&lt;p&gt;If you are interested in customizing DNS behaviour for your needs, we would suggest going through the book “Learning CoreDNS” by Cricket Liu and John Belamaric.&lt;br&gt;
Book provides a detailed overview of different CoreDNS plugins with their use cases.&lt;br&gt;
It also covers CoreDNS + Kubernetes integration in depth.&lt;/p&gt;

&lt;p&gt;If you are running an appropriate number of instances of CoreDNS in your Kubernetes cluster or not is one of the critical factors to decide.&lt;br&gt;
It’s recommended to run a least two instances of the CoreDNS server for a better guarantee of DNS requests being served.&lt;br&gt;
Depending upon the number of requests being served, nature of requests, number of workloads running on the cluster, and size of cluster you may need to add extra instances of CoreDNS or configure HPA (Horizontal Pod Autoscaler) for your cluster.&lt;br&gt;
Factors like the number of requests being served, nature of requests, number of workloads running on the cluster and cluster size should help you in deciding the number of CoreDNS instances.&lt;br&gt;
You may need to add extra instances of CoreDNS or configure HPA (Horizontal Pod Autoscaler) for your cluster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;This blog post tries to highlight the importance of the DNS request cycle in Kubernetes, and many times you would end up in a situation where you start with “it’s not DNS” but end up “it’s always DNS !”.&lt;br&gt;
So be careful of these landmines.&lt;/p&gt;

&lt;p&gt;Enjoyed the article? Let's connect on &lt;a href="https://twitter.com/sanketsudake"&gt;Twitter&lt;/a&gt; and start a conversation.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>coredns</category>
      <category>devops</category>
      <category>dns</category>
    </item>
  </channel>
</rss>
