<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[byjos.dev Blog RSS Feed]]></title><description><![CDATA[Łukasz Byjoś website - blog and thoughts about serverless and other topics]]></description><link>https://byjos.dev</link><generator>GatsbyJS</generator><lastBuildDate>Mon, 22 Sep 2025 19:41:21 GMT</lastBuildDate><item><title><![CDATA[When AIs start gossiping about your code - Claude Code with Gemini CLI]]></title><description><![CDATA[What happens when you combine Claude Code’s conversational coding with Gemini CLI’s massive context window? A workflow that transforms how…]]></description><link>https://byjos.dev/claude-gemini-workflow/</link><guid isPermaLink="false">https://byjos.dev/claude-gemini-workflow/</guid><pubDate>Thu, 07 Aug 2025 17:00:00 GMT</pubDate><content:encoded>&lt;h4&gt;What happens when you combine Claude Code’s conversational coding with Gemini CLI’s massive context window? A workflow that transforms how we understand and work with complex codebases.&lt;/h4&gt;
&lt;h2&gt;The problem with large codebases&lt;/h2&gt;
&lt;p&gt;Ever joined a team and faced a codebase with hundreds of files? You know the feeling - opening file after file, trying to piece together how everything connects. Traditional grep commands and IDE searches help, but they can’t answer the big questions: “How does navigation work across all these Flutter screens?” or “Is state management consistent throughout the app?”&lt;/p&gt;
&lt;p&gt;That’s where I discovered something interesting. &lt;strong&gt;Claude Code&lt;/strong&gt; excels at detailed, conversational coding work, but it hits context limits with large projects. &lt;strong&gt;Gemini CLI&lt;/strong&gt;, with its massive context window and planning capabilities, can digest entire codebases and provide strategic insights.&lt;/p&gt;
&lt;p&gt;But here’s the key insight: they’re not separate tools you switch between. Claude Code can call Gemini CLI directly, creating something powerful.&lt;/p&gt;
&lt;h2&gt;The dream team: Claude + Gemini + Human&lt;/h2&gt;
&lt;p&gt;Think about it this way: &lt;strong&gt;Claude Code&lt;/strong&gt; (even with Sonnet) is exceptional at actual coding - writing functions, debugging, refactoring. &lt;strong&gt;Gemini CLI&lt;/strong&gt; brings massive context understanding and strategic planning capabilities. Add yourself as the &lt;strong&gt;code reviewer and senior software engineer&lt;/strong&gt;, and you’ve got a small, experienced development team.&lt;/p&gt;
&lt;p&gt;Claude handles the implementation details, Gemini provides the big-picture strategy, and you make the architectural decisions. It’s like having two consultants who never argue over who gets credit for fixing your mess 🤝&lt;/p&gt;
&lt;h2&gt;When Claude Code hits its limits&lt;/h2&gt;
&lt;p&gt;Working on a Flutter project recently, we hit a frustrating bug. Users reported that switching between tabs caused “LateInitializationError” crashes. The app used GetX for state management, and the error seemed to happen inconsistently across different screens.&lt;/p&gt;
&lt;p&gt;Claude Code could help debug individual controllers beautifully, but this felt like a system-wide issue. The bug report mentioned it happened “sometimes on the Profile tab, sometimes on Settings, but always after rapid tab switching.”&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The kind of bug report that makes you question your life choices and wonder if you should have become a baker instead.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That’s when I realized Claude Code could bring in its research assistant.&lt;/p&gt;
&lt;h2&gt;The actual workflow: Starting with Claude&lt;/h2&gt;
&lt;p&gt;Here’s the workflow that’s become second nature. I start where I always do:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;claude&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This opens Claude Code, and I switch to &lt;strong&gt;plan mode&lt;/strong&gt;. But now I copy-paste the entire bug report, add my own context about what might be happening, and mention which files seem related.&lt;/p&gt;
&lt;p&gt;“We’re getting LateInitializationError crashes in our Flutter GetX app. I think it’s related to how we’re initializing controllers in &lt;code class=&quot;language-text&quot;&gt;main.dart&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;profile_controller.dart&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;settings_controller.dart&lt;/code&gt;. Can you analyze the entire codebase structure and help fix this?”&lt;/p&gt;
&lt;h2&gt;Real-world example: Fixing GetX late initialization&lt;/h2&gt;
&lt;p&gt;Here’s exactly how this played out:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Starting the conversation with context:&lt;/strong&gt;
I pasted the full bug report, stack traces, and added: “This seems to happen when users switch tabs rapidly. I suspect it’s related to GetX controller lifecycle. Files that might be relevant: &lt;code class=&quot;language-text&quot;&gt;/lib/controllers/&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;/lib/screens/profile/&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;/lib/screens/settings/&lt;/code&gt;.”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Claude Code coordinates the analysis:&lt;/strong&gt;
Claude Code is smart enough to call Gemini CLI with exactly what it needs for analysis. I don’t see the actual command it runs, but it gets a comprehensive view of how GetX controllers are initialized across the entire codebase.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Strategic insight emerges:&lt;/strong&gt;
The analysis revealed the issue: some controllers were being initialized with &lt;code class=&quot;language-text&quot;&gt;Get.put()&lt;/code&gt; in &lt;code class=&quot;language-text&quot;&gt;initState()&lt;/code&gt;, while others used &lt;code class=&quot;language-text&quot;&gt;Get.lazyPut()&lt;/code&gt; in routes. When users switched tabs rapidly, some controllers were disposed while others were still trying to initialize.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Implementation together:&lt;/strong&gt;
Claude Code and I worked through the fix:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Standardized all controller initialization to use &lt;code class=&quot;language-text&quot;&gt;Get.lazyPut()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Added proper dependency injection in the main binding&lt;/li&gt;
&lt;li&gt;Ensured controllers had proper lifecycle management&lt;/li&gt;
&lt;li&gt;Added null checks for late-initialized variables&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;5. The code review step:&lt;/strong&gt;
Here’s where it gets interesting. After Claude Code finished all the changes, I asked: “Can you use Gemini CLI to review these changes as an external peer? Check if the fix is consistent with GetX best practices across the entire codebase.”&lt;/p&gt;
&lt;h2&gt;The code review advantage&lt;/h2&gt;
&lt;p&gt;This review step was eye-opening. Gemini CLI, acting as an external peer reviewer, caught a few things we missed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One controller still used the old initialization pattern&lt;/li&gt;
&lt;li&gt;A potential memory leak in the settings controller&lt;/li&gt;
&lt;li&gt;Suggested adding error boundaries around tab switching&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s like having an external senior developer review your changes after implementation. Claude Code recently got &lt;a href=&quot;https://www.anthropic.com/news/automate-security-reviews-with-claude-code&quot;&gt;automated security review capabilities&lt;/a&gt;, but using Gemini CLI as a code reviewer gives you that external perspective on &lt;strong&gt;any&lt;/strong&gt; type of change.&lt;/p&gt;
&lt;p&gt;The beautiful thing is it all happens in one conversation: “Claude, now ask Gemini to review these changes as if they’re a peer developer who hasn’t been involved in this implementation.”&lt;/p&gt;
&lt;h2&gt;Why this changes everything&lt;/h2&gt;
&lt;p&gt;What I love most is how this workflow handles everything from bug reports to feature requests. The pattern is always:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Start in Claude Code&lt;/strong&gt; - paste the bug report, task description, add context&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Provide guidance&lt;/strong&gt; - mention which files might be relevant based on your experience&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Let them collaborate&lt;/strong&gt; - Claude Code and Gemini CLI work together on analysis and planning&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implement together&lt;/strong&gt; - detailed coding work with Claude Code&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;External review&lt;/strong&gt; - Gemini CLI reviews as a peer developer who wasn’t involved in implementation&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Whether it’s fixing “late” initialization issues with GetX tabs or implementing new features, you get strategic overview, detailed implementation, and external code review in one seamless conversation.&lt;/p&gt;
&lt;h2&gt;The small experienced team effect&lt;/h2&gt;
&lt;p&gt;The key insight is that this creates something greater than the sum of its parts. &lt;strong&gt;Claude Code&lt;/strong&gt; excels at coding conversations, &lt;strong&gt;Gemini CLI&lt;/strong&gt; provides strategic context, and &lt;strong&gt;you&lt;/strong&gt; provide the architectural vision and code review.&lt;/p&gt;
&lt;p&gt;Together, it feels like working with a small, experienced development team where everyone has specialized strengths but communicates seamlessly.&lt;/p&gt;
&lt;h2&gt;Getting started&lt;/h2&gt;
&lt;p&gt;If you’re curious to try this workflow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;a href=&quot;https://github.com/google-gemini/gemini-cli&quot;&gt;Gemini CLI&lt;/a&gt; and set it up&lt;/li&gt;
&lt;li&gt;Next time you’re working on a complex codebase, start with &lt;code class=&quot;language-text&quot;&gt;claude&lt;/code&gt; as usual&lt;/li&gt;
&lt;li&gt;Switch to plan mode and ask Claude Code to use Gemini CLI for big-picture analysis&lt;/li&gt;
&lt;li&gt;Let the conversation flow naturally between strategic planning and detailed implementation&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;What’s next&lt;/h2&gt;
&lt;p&gt;This workflow has transformed how I approach complex projects, but I’m still discovering new applications. Recently, I’ve been asking Claude Code to use Gemini CLI for architecture reviews before major refactors, and the insights have been remarkable.&lt;/p&gt;
&lt;p&gt;The real magic isn’t just about having better tools - it’s about creating a development environment where strategic thinking, detailed implementation, and code review happen in one seamless conversation. You end up building better software because you understand systems more deeply while maintaining the creative, conversational development experience we love.&lt;/p&gt;
&lt;p&gt;The three-way collaboration between Claude Code, Gemini CLI, and human insight really does feel like working with a small, experienced development team. Each member brings unique strengths, but together they create something more powerful than any individual tool.&lt;/p&gt;
&lt;p&gt;Have you tried combining AI tools in your development workflow? I’d love to hear about your experiences and what team dynamics work best for different types of projects.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[GCP Workload Identity Federation - connecting with GitLab]]></title><description><![CDATA[Wondering if you can securely connect from Gitlab runner to GCP without generating service account keys? In this short post I’ll try to show…]]></description><link>https://byjos.dev/workload-identity-federation-gitlab/</link><guid isPermaLink="false">https://byjos.dev/workload-identity-federation-gitlab/</guid><pubDate>Wed, 14 Sep 2022 17:00:00 GMT</pubDate><content:encoded>&lt;h4&gt;Wondering if you can securely connect from Gitlab runner to GCP without generating service account keys? In this short post I’ll try to show you how to do it&lt;/h4&gt;
&lt;p&gt;All methods I found for now about connecting from Gitlab runner to gcloud via CLI or API, included the step of generating Service Account key and using it in job through CI/CD variables. For a few months, we are able to use &lt;a href=&quot;https://cloud.google.com/iam/docs/workload-identity-federation&quot;&gt;Workload Identity Federation&lt;/a&gt; for making this connection more secure.&lt;/p&gt;
&lt;h2&gt;Workload Identity Federation&lt;/h2&gt;
&lt;p&gt;As you might know (or not?) generating service account keys is not a very secure practice if keys are not rotated. If a key like that is leaked you will need a block service account which may cause even production environments to stop working and then do rotation of keys.&lt;/p&gt;
&lt;p&gt;Recently you might have heard about the &lt;a href=&quot;https://twitter.com/cz_binance/status/1543905416748359680&quot;&gt;leak of over 1 billion&lt;/a&gt; records of private citizens data because a key was leaked into a blogpost.&lt;/p&gt;
&lt;p&gt;Workload Identity Federation (WIF) basically allows you to make secure connections between Gitlab (or other supported providers e.g. through OIDC) and Google Cloud.&lt;/p&gt;
&lt;p&gt;Instead of generating access tokens from Service Account key, a &lt;a href=&quot;https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-about&quot;&gt;short lived&lt;/a&gt; JWT token is used. This helps to increase security because even if a token is leaked it can’t be used in a short moment to get access to resources.&lt;/p&gt;
&lt;p&gt;The same for generated json files for Workload Identity Federation. File can be leaked as it is not storing any secure information by itself. Without an option to sign a request to STS (Security Token Service) on Google Cloud, an attacker cannot acquire JWT token to access resources on your project.&lt;/p&gt;
&lt;p&gt;From where Google Cloud STS knows that request to it is valid and signed? Gitlab sign request with its keys and it can be validated using published Gitlab OIDC configuration there &lt;a href=&quot;https://gitlab.com/.well-known/openid-configuration&quot;&gt;https://gitlab.com/.well-known/openid-configuration&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Of course we should remember to use least privilege security principle and Service Account which we connect to WIF should have only required IAM permissions.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b1ae701fed6a555482db0f1bcd4917ba/ddced/wif_1.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 35.44303797468354%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAHABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHauJAr/8QAFBABAAAAAAAAAAAAAAAAAAAAEP/aAAgBAQABBQJ//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFhAAAwAAAAAAAAAAAAAAAAAAABAx/9oACAEBAAY/AlT/xAAYEAEBAAMAAAAAAAAAAAAAAAABACFRYf/aAAgBAQABPyEzB2R2v//aAAwDAQACAAMAAAAQjC//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAVEQEBAAAAAAAAAAAAAAAAAAAAAf/aAAgBAgEBPxCI/8QAGxABAAICAwAAAAAAAAAAAAAAAQAhETFRYdH/2gAIAQEAAT8QyCYd0EcCx1Uzq1cHk//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Modified graphic from blog post&quot;
        title=&quot;Modified graphic from blog post&quot;
        src=&quot;/static/b1ae701fed6a555482db0f1bcd4917ba/828fb/wif_1.jpg&quot;
        srcset=&quot;/static/b1ae701fed6a555482db0f1bcd4917ba/ff44c/wif_1.jpg 158w,
/static/b1ae701fed6a555482db0f1bcd4917ba/a6688/wif_1.jpg 315w,
/static/b1ae701fed6a555482db0f1bcd4917ba/828fb/wif_1.jpg 630w,
/static/b1ae701fed6a555482db0f1bcd4917ba/0ede0/wif_1.jpg 945w,
/static/b1ae701fed6a555482db0f1bcd4917ba/ddced/wif_1.jpg 1100w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;
&lt;em&gt;Modified graphic from blog post&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Feature described below was working with Github as it has support for OIDC tokens. Gitlab enabled this feature too and using &lt;a href=&quot;https://docs.gitlab.com/ee/ci/cloud_services/&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;CI_JOB_JWT_V2&lt;/code&gt;&lt;/a&gt; you can leverage Workload Identity Federation for secure connection.&lt;/p&gt;
&lt;h2&gt;The script&lt;/h2&gt;
&lt;p&gt;Script below is based on the GCP &lt;a href=&quot;https://cloud.google.com/blog/products/identity-security/enabling-keyless-authentication-from-github-actions&quot;&gt;Blogpost&lt;/a&gt; tutorial on how to connect to Github.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p class=&quot;blockquote-title&quot;&gt;Important step&lt;/p&gt;
&lt;p&gt;Important change to blogpost code, is to allow Gitlab to be used as an audience in the Workload Identity Federation. Now you can set this too by hand when creating Pool from Google Cloud Console.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p class=&quot;blockquote-title&quot;&gt;Important Step&lt;/p&gt;
&lt;p&gt;Very important is to remember to set the audience to limit access to Identity Pool only to for instance given Gitlab project ID. It can be email or any other parameter from request. To do that, set the env variable and run the script.
SUB=/attribute.project_id/29450825&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#First, set PROJECT_ID example export PROJECT_ID=my-project&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#Second, set so called SUB to make this connection work only with given Gitlab ID project.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#Example of sub export SUB=/attribute.project_id/29450825&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#Last step, set Service Account name which will be used as a connection from Gitlab. export SA_NAME=&quot;my-service-account&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;${PROJECT_ID}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;&gt; PROJECT_ID not set&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PROJECT_ID set&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;${SUB}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;&gt; SUB not set, setting to *&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;SUB&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/*&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SUB set&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;${SA_NAME}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;&gt; Service account name (SA_NAME) not set&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SA_NAME set&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;token assign-left variable&quot;&gt;SERVICE_ACCOUNT_NAME&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${SA_NAME}&lt;/span&gt;@&lt;span class=&quot;token variable&quot;&gt;${PROJECT_ID}&lt;/span&gt;.iam.gserviceaccount.com&quot;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;PROJECT_NUMBER&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;gcloud projects describe $PROJECT_ID &lt;span class=&quot;token parameter variable&quot;&gt;--format&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;value(projectNumber)&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token assign-left variable&quot;&gt;WORKLOAD_IDENTITY_POOL_ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gitlab-identity-pool&quot;&lt;/span&gt;
gcloud config &lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; project &lt;span class=&quot;token variable&quot;&gt;${PROJECT_ID}&lt;/span&gt;

&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;&gt; Creating Workload Identity Pool...&quot;&lt;/span&gt;

gcloud iam workload-identity-pools create &lt;span class=&quot;token string&quot;&gt;&quot;gitlab-identity-pool&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--project&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${PROJECT_ID}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--location&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;global&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --display-name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Gitlab identity pool&quot;&lt;/span&gt;

&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;&gt; Done. Creating OIDC provider in pool...&quot;&lt;/span&gt;

gcloud iam workload-identity-pools providers create-oidc &lt;span class=&quot;token string&quot;&gt;&quot;gitlab&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--project&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${PROJECT_ID}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--location&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;global&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --workload-identity-pool&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${WORKLOAD_IDENTITY_POOL_ID}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --display-name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Gitlab OIDC provider&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --attribute-mapping&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;google.subject=assertion.sub,attribute.aud=assertion.aud,attribute.env=assertion.environment,attribute.project_id=assertion.project_id&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  --issuer-uri&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://gitlab.com&quot;&lt;/span&gt;

&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;&gt; Done. Enabling gitlab as audience...&quot;&lt;/span&gt;

gcloud iam workload-identity-pools providers update-oidc gitlab --allowed-audiences&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;https://gitlab.com &lt;span class=&quot;token parameter variable&quot;&gt;--location&lt;/span&gt; global --workload-identity-pool &lt;span class=&quot;token variable&quot;&gt;$WORKLOAD_IDENTITY_POOL_ID&lt;/span&gt;

&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;&gt; Done. Setting service account permissions...&quot;&lt;/span&gt;

gcloud iam service-accounts add-iam-policy-binding &lt;span class=&quot;token variable&quot;&gt;$SERVICE_ACCOUNT_NAME&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--project&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${PROJECT_ID}&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--role&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;roles/iam.workloadIdentityUser&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--member&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;principalSet://iam.googleapis.com/projects/&lt;span class=&quot;token variable&quot;&gt;${PROJECT_NUMBER}&lt;/span&gt;/locations/global/workloadIdentityPools/&lt;span class=&quot;token variable&quot;&gt;${WORKLOAD_IDENTITY_POOL_ID}&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;${SUB}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;&gt; Done. Generating json configuration file...&quot;&lt;/span&gt;

gcloud iam workload-identity-pools create-cred-config &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    projects/&lt;span class=&quot;token variable&quot;&gt;$PROJECT_NUMBER&lt;/span&gt;/locations/global/workloadIdentityPools/&lt;span class=&quot;token variable&quot;&gt;$WORKLOAD_IDENTITY_POOL_ID&lt;/span&gt;/providers/gitlab &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    --service-account&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$SERVICE_ACCOUNT_NAME&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    --output-file&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;gitlab_token.json &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    --credential-source-file&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;gitlab_token &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
    --credential-source-type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;text

&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;&gt; Done. Use below configuration file in Gitlab project&quot;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; gitlab_token.json&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You’ll get a file named gitlab_token.json which you can safely use and share in your project CI/CD variables. Example usage with gcloud CLI is&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#If gitlab_token set as variable in Gitlab&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; echo $CICD_SA_JSON &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;CI_PROJECT_DIR&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/service_key.json
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; export GOOGLE_APPLICATION_CREDENTIALS=$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;CI_PROJECT_DIR&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/service_key.json
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; echo $CI_JOB_JWT_V2 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; gitlab_token
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; gcloud auth login &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;cred&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;file=$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;CI_PROJECT_DIR&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/service_key.json &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;activate &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;project $PROJECT_ID&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#If token set as File tyle in Gitlab&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; export GOOGLE_APPLICATION_CREDENTIALS=$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;CICD_SA_JSON&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; echo $CI_JOB_JWT_V2 &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; gitlab_token
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; gcloud auth login &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;cred&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;file=$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;CICD_SA_JSON&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;activate &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;project $PROJECT_ID&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Job script can be different from case to case so feel free to ask me in comments or reach me on Twitter with questions.&lt;/p&gt;
&lt;p&gt;I hope this will help you to make your pipelines safer. If you have any comments or improvement ideas, please share it :)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Google Cloud Run - hot service, happy users]]></title><description><![CDATA[Most of us like hot things. Hot meal, hot bath or hot weather. Some of us also like the hot state of serverless services without paying too…]]></description><link>https://byjos.dev/cloud-run-hot-service/</link><guid isPermaLink="false">https://byjos.dev/cloud-run-hot-service/</guid><pubDate>Fri, 07 Jan 2022 17:00:00 GMT</pubDate><content:encoded>&lt;h4&gt;Most of us like hot things. Hot meal, hot bath or hot weather. Some of us also like the hot state of serverless services without paying too much for it. In this post you can find out how to keep Cloud Run in hot state for free🔥&lt;/h4&gt;
&lt;h2&gt;Cold and Hot states&lt;/h2&gt;
&lt;p&gt;In a &lt;a href=&quot;https://byjos.dev/cloud-run-intro/&quot;&gt;previous&lt;/a&gt; blogpost you could read what Cloud Run is and it’s basics. For serverless services we can use the convention of having service in cold and hot states. Best scenario is when our service is always in hot state as it’s ready for responding to requests instead of booting every time.&lt;/p&gt;
&lt;h3&gt;Cold State&lt;/h3&gt;
&lt;p&gt;Service is “turned off” and sleeping. Often we are not paying for it and any incoming request needs to wait until service is woken up and ready for receiving requests.&lt;/p&gt;
&lt;p&gt;In Cloud Run, &lt;span style=&quot;background-color: rgba(255, 152, 0, 0.38)&quot;&gt;cold state&lt;/span&gt; means that the Docker container is turned off and before the request can be handled we need to wait for the startup process (entrypoint script + app startup) of our program to end. It can differ from a few milliseconds to even a few minutes if we have a monolithic application (I saw this behaviour when I tried to run Keycloak on Cloud Run).&lt;/p&gt;
&lt;p&gt;I have prepared a simple Go app which sleeps 5s before starting the server. In logs we can see that this will happen every time when an app is killed/exited and started again or a new revision is created. Users or other services will need to wait until all startup is done.&lt;/p&gt;
&lt;p&gt;Other services calling it will have to wait and will be billed for it, so it’s not the best situation for us.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/eb475063b1be97dea9628b23b79f11e8/6e7b6/cold_state_logs.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 17.72151898734177%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAn0lEQVR42m2OzRLCMAiE+/7vp1dN1dYmAQL5GW0SR2r1JqcdFna/gUJAohijB1zX1TmYZrtYb67LYczmZk9n44GYGfWOCABUh8Ap5UFiEpGcC7PUWlWrEdRnYYk5597769/oftCAmFIpRcu/z8yqlQhIHs/aWqu17RH9N/v/oA30wVaqDdvjfLcOcJzcUbEnNOZird+wifQGEYOysQKGNzaO41lvTLBBAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;GPC logs showing slow startup of service from cold state&quot;
        title=&quot;GPC logs showing slow startup of service from cold state&quot;
        src=&quot;/static/eb475063b1be97dea9628b23b79f11e8/f058b/cold_state_logs.png&quot;
        srcset=&quot;/static/eb475063b1be97dea9628b23b79f11e8/c26ae/cold_state_logs.png 158w,
/static/eb475063b1be97dea9628b23b79f11e8/6bdcf/cold_state_logs.png 315w,
/static/eb475063b1be97dea9628b23b79f11e8/f058b/cold_state_logs.png 630w,
/static/eb475063b1be97dea9628b23b79f11e8/40601/cold_state_logs.png 945w,
/static/eb475063b1be97dea9628b23b79f11e8/78612/cold_state_logs.png 1260w,
/static/eb475063b1be97dea9628b23b79f11e8/6e7b6/cold_state_logs.png 1491w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Hot State&lt;/h3&gt;
&lt;p&gt;This means that our app is ready for receiving requests. In a non serverless world it’s equivalent to just running an application all the time.&lt;/p&gt;
&lt;p&gt;In Cloud Run &lt;span style=&quot;background-color: rgba(255, 152, 0, 0.38)&quot;&gt;hot state&lt;/span&gt; means that our container is not sleeping and is ready to handle requests even when in recent seconds/minutes it did not get any request. When you get eg. one request per second or half minute, it should be handled without any delay.&lt;/p&gt;
&lt;p&gt;We need to also remember about CPU allocation which can be “request only” or “all the time” when an instance is live.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c811542620939f844a1f8bad6c62d086/29007/cpu_allocation_modes_gcp.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.32911392405063%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAABuElEQVR42n1RTW+bQBD1767UWHFzydWq+6EovVRKWrXHHhNFjT/YxSQy2GmwkZO0TgIYAwbvAgu7SxawW/vSp6fV7Gie5s1MLd9ClmWEkBVCc2fh+YHnLwX9LXobLpcBpbS2LU7TFGM8NqaddvuqD/sQCHZ74LIjdboSBECRwVUfAKl3dn4h9Gsx57wSJ0kigiefqX+obrKJxXzMq5qZy7QZHc7ovcOqzE5noQyCIM/ZnU0GD/GPa9T45h6fB8PfsUhOrUS5iwUnz0nO2VqMEDJN0y4RhuFfI+JhNI+SHMelu00PvolrValYlVhAlqZBjB8fRmMdti1NNlXFVuFCM6YKbf/UDaVjqV1TG00V0rvkKNyxHSH87NoXN2df4emB8rEBWq97zVdS80T+Eg+0075IftiXW5/kz+FgQDEuxCyOVmEBcYEoiorhKWGcpywjNK2siRFiSmg5ajXU2jbDCK1C1yvgeq7h36vz2+FiMhJ0DRFojq5Zv0bOWGSK71zX7Nsoi3dsY4TnC+f45vsb+O5QOTqQ3++BZr3kPnxb38R1qdmArSdk/7uzACuB0iggq5Ag8f6HlLMX7lJT0+RkCbMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Image from Google Cloud Blog showing differences in CPU allocation&quot;
        title=&quot;Image from Google Cloud Blog showing differences in CPU allocation&quot;
        src=&quot;/static/c811542620939f844a1f8bad6c62d086/f058b/cpu_allocation_modes_gcp.png&quot;
        srcset=&quot;/static/c811542620939f844a1f8bad6c62d086/c26ae/cpu_allocation_modes_gcp.png 158w,
/static/c811542620939f844a1f8bad6c62d086/6bdcf/cpu_allocation_modes_gcp.png 315w,
/static/c811542620939f844a1f8bad6c62d086/f058b/cpu_allocation_modes_gcp.png 630w,
/static/c811542620939f844a1f8bad6c62d086/40601/cpu_allocation_modes_gcp.png 945w,
/static/c811542620939f844a1f8bad6c62d086/78612/cpu_allocation_modes_gcp.png 1260w,
/static/c811542620939f844a1f8bad6c62d086/29007/cpu_allocation_modes_gcp.png 1600w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is the best scenario for us and our users. From my experience, on production environments with stable and ongoing traffic we should have a hot state all the time.&lt;/p&gt;
&lt;p&gt;But in case when we have differential traffic and non 24/7 our users might experience slowdowns or even timeouts. Below I’ll explain how to prevent this and keep users, business and devops happy.&lt;/p&gt;
&lt;p&gt;You should &lt;a href=&quot;https://cloud.google.com/blog/topics/developers-practitioners/3-ways-optimize-cloud-run-response-times&quot;&gt;optimize&lt;/a&gt; your app startup too as there is no guarantee that any of keeping hot methods will always work. If you don’t want to play with this you can always set a minimum instance count and have a hot state all the time but pay for it.&lt;/p&gt;
&lt;h2&gt;Rub your services?&lt;/h2&gt;
&lt;p&gt;When you are feeling cold you drink something hot, put on more clothes or rub yourself. I do not recommend trying the first two with your services but the third one option is possible!&lt;br&gt;
&lt;em&gt;If you manage to do the first two, contact me!&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Are you alive aka health check&lt;/h3&gt;
&lt;p&gt;The simplest option is to do a regular health check of your service to monitor its state. This is what you should do by default (monitoring services). &lt;br&gt;
Using a health check can be different depending on access type to your service.&lt;/p&gt;
&lt;h4&gt;Case 1 - my service has public URL and no auth&lt;/h4&gt;
&lt;p&gt;If you allow a public URL in Cloud Run (everyone can access it, IAM set to AllUsers Cloud Run Invoker) you can use any ping/health check service you have. In this scenario we can use GCP Operations &lt;a href=&quot;https://cloud.google.com/monitoring/uptime-checks&quot;&gt;uptime check&lt;/a&gt; and endpoint in your service which can even respond with only “pong” on default &lt;code class=&quot;language-text&quot;&gt;/&lt;/code&gt; path or &lt;code class=&quot;language-text&quot;&gt;/health&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To set this go to GCP Console -&gt; Monitoring -&gt; &lt;a href=&quot;https://console.cloud.google.com/monitoring/uptime&quot;&gt;Uptime Check&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set name of your uptime check. I’ll call mine “rub-my-service”.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b2bbc30683eb79e876044635d16d7f4d/f0551/public_url_1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 49.36708860759494%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAvUlEQVR42pWQwQ6DIBBE+f9/67EHU6mxsYlVUUSUAgt2NGkPTRrqS+DA7uzMwoQQec6LouCcl2XJ+bWq7lrr6TcoDlI13ciIvFJSqUlKicI4ynme1xQUovWR4RgbrX0S0VdHTMFuD3fK1CU7t52AwHsf3iT9GQZAgKjGGNzYVmGHbTGNUkIMBzTVdY2fW5bFOUf/scWGmCj0QrTNBvz3lwQI+xFjzBriepQ9dqCmt4OyMYZjYrhDjxiIctT5BUIqSqyGrtJvAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;First step of creating uptime check on GCP Console&quot;
        title=&quot;First step of creating uptime check on GCP Console&quot;
        src=&quot;/static/b2bbc30683eb79e876044635d16d7f4d/f058b/public_url_1.png&quot;
        srcset=&quot;/static/b2bbc30683eb79e876044635d16d7f4d/c26ae/public_url_1.png 158w,
/static/b2bbc30683eb79e876044635d16d7f4d/6bdcf/public_url_1.png 315w,
/static/b2bbc30683eb79e876044635d16d7f4d/f058b/public_url_1.png 630w,
/static/b2bbc30683eb79e876044635d16d7f4d/f0551/public_url_1.png 862w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Next we need to set how Monitoring will reach our service. For Cloud Run we set a public URL and optionally path to the endpoint. For basic uptime check we can leave default options. For the scheme we set HTTPS (as we can’t have an insecure endpoint with Cloud Run &amp;#x3C;3) and provide a url to it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1f30a230f4341b3f1a52b6d2210409a0/914ae/public_url_2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 113.9240506329114%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAIAAACEf/j0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB8klEQVR42pVUiZKrIBDM/39gXiW7uQQPUAkiIsrhjhDdbPZIXtcUNQU0MEezKbl5Q6rIMELYOTf9DzbX1iLaY3Q5Xy5932uth2EARyn19KyN994a0y0ADjCjb631v2Mmw/HgnU6n/X7vvgLI5htgUgUsNy9wryFunsnT5CHOBKUAhFCcfTVhQBadeU94itFut4OHjHeIz/srYZDeuq7hZkIIxjhJknrB+Xx+Tq6qOsuyPM+3262UEhZiPv3vFp7t55jLkhIC3PR4PFgz8itTXbce8Q1+iqWCZSgA421GOeOyoIxUzSnJSMUHM3W9VdrdW9c7PThj/e3mXttzKpKU4YKlxTUvG1q1pBKisw/WSNPp6YLpv/cc6IE82JSqvGwxEbhoUhpGIrh00LwPBpNF1aVUOr90GMIppSW8xMw9MJuxbjR2HM3Ngj8MIyxxLjjnt/YEtG0rhFi7J3ab987HMTphJ3DKsiSk+EwYlBSKvGbTBKlAFVbB9AHgQCFXtW1iSzHGgL+S4WbYGrWp7xA1t9bvFjOh9HA8QG/xprHh8T9KIqroGvCpKtVJaAyQYAjP3sX+CIiIAspyjdn2g5fay97J3rbKqeGl/yjEbKxQDj4zMCZM3Rgu/xLm15/Ezd3Tabc0/Mt6DvWzTOim1Q+ieUr+AM7rPdI4KbujAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Second step of creating uptime check on GCP Console with configuration of HTTPS endpoint&quot;
        title=&quot;Second step of creating uptime check on GCP Console with configuration of HTTPS endpoint&quot;
        src=&quot;/static/1f30a230f4341b3f1a52b6d2210409a0/f058b/public_url_2.png&quot;
        srcset=&quot;/static/1f30a230f4341b3f1a52b6d2210409a0/c26ae/public_url_2.png 158w,
/static/1f30a230f4341b3f1a52b6d2210409a0/6bdcf/public_url_2.png 315w,
/static/1f30a230f4341b3f1a52b6d2210409a0/f058b/public_url_2.png 630w,
/static/1f30a230f4341b3f1a52b6d2210409a0/914ae/public_url_2.png 860w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Next we can leave default settings for response timeout, skip content matching and not set alerts (but I recommend setting it). Before clicking “save” click “test” and you should see a green box with a successful response.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7ef359810abb8dad7a30a5e4ad84a9d8/76cea/public_url_3.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 23.417721518987342%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAmklEQVR42o3PSw6CMBAA0B7XI3gKF+6MZ3DlQVzV2E8o6KKfBAMNxXYo1oJxJwlvM5/MJDMIwgQAYozDDALMjewXFqBLcb09ikqUGGNCCKWUMZYTIURZlZxzrbW1tv0Hed+F4L7yUO96773rZm6KrnevBWizu+9PZoxBKZ1SaptGSgkwpBXQ9iCOZ/Ueh7p+5jofaIzJn69Z/gBZ2RwJqtBqRAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Third step of creating uptime check on GCP Console. Image show successful request to given endpoint.&quot;
        title=&quot;Third step of creating uptime check on GCP Console. Image show successfull request to given endpoint.&quot;
        src=&quot;/static/7ef359810abb8dad7a30a5e4ad84a9d8/f058b/public_url_3.png&quot;
        srcset=&quot;/static/7ef359810abb8dad7a30a5e4ad84a9d8/c26ae/public_url_3.png 158w,
/static/7ef359810abb8dad7a30a5e4ad84a9d8/6bdcf/public_url_3.png 315w,
/static/7ef359810abb8dad7a30a5e4ad84a9d8/f058b/public_url_3.png 630w,
/static/7ef359810abb8dad7a30a5e4ad84a9d8/76cea/public_url_3.png 799w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This will keep our service in hot state all the time with minimal cost (even 0$ if we keep it in free tier or requests/cpu/memory).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p class=&quot;blockquote-title&quot;&gt;Runtime environment generation differences. &lt;/p&gt;
&lt;p&gt;I have observed that for the First Generation runtime environment we can use a 5 minutes check frequency as it’s enough to keep the container in a hot state while when I was using Second Generation (beta) I had to set a 1 minute frequency check as my container tends to go to a cold state during a silent period.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Case 2 - my service has GCP Auth enabled&lt;/h4&gt;
&lt;p&gt;Now stuff gets a little more complicated. For now I did not find a way to leverage Uptime Check service with Auth enabled. When you try you’ll get just 403 responses and requests will not reach your app/container as they are blocked at GCP infra level.&lt;/p&gt;
&lt;p&gt;We have at least two options:&lt;/p&gt;
&lt;h5&gt;&lt;strong&gt;I’m a greedy option&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;Often you have another service which is using your “authed” service and is a public one. Use it to do a health check of “authed” one with the previous strategy. If you use trace with your services you’ll be able to additionally monitor performance of this chain of requests.&lt;/p&gt;
&lt;h5&gt;&lt;strong&gt;I can spend penny option&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;If you are ok with spending &lt;a href=&quot;https://cloud.google.com/scheduler/pricing&quot;&gt;“$0.10 per job per month”&lt;/a&gt; you can use Cloud Scheduler for this. It can use IAM Service Account with Cloud Invoker role which enables us to ping service with Auth enabled.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First we set the name, crontab and timezone of the job. I’ll set it to ping my service every 5 minutes.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/99546cee38cbdf79d40d30511b74ec32/bad1b/auth_url_1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 82.91139240506328%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAIAAABSJhvpAAAACXBIWXMAAAsTAAALEwEAmpwYAAABoElEQVR42pVTi26DIBT1/39t2Zpu2dbFNVnWBxR5qQiC2O4ote2ydY8TIwice889XLPQ7W0bvW8B1zo/zpxzMcbDb8jeaLh5Vo8Ps/n8Pl++LpfLx6en2d0tFxLbfd/vr2Agp+31ekUIqYCyNLWJ8ROn/w6QlqWhLEvOBaWUUMp2rGka5wbxA6zFgatkxAa54AUSo2acNyPqEVjsviODlaXJZrN5WSzeV2spldIqhICSpuJ+k43T1llk01rXxvgQ4hVc8o+yCSX5aw7xyeFT7C/Z0nOMcjKsglxUCwm4Z+9DNwKfaeJHhC70sQPjLBuAYAFIKfESQsN8weF/wYdRCA4roKs2VuhWVy0o53tWSm2326quEQ95sJhsTwjeYxFbPsSyDqbpLt3uKSF5nm8JYWxXFAUhFAIYY9bas+1TY6Fr0AiIdiQ3jdFKQR8DlfP0LgYwPaGs4IsSUrW+S05msA2xdoUmlOvyeG6467FIDLBCj59YR0CptNCQPfU2gKaIcX/4JxI5qjqsmGOy/eE3+lz4RIaNtg2V8Y31550/ZP4A7cLanNFC3GYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;First step of creating GCP Cloud Scheduler with cron tab set to do job every 5 minutes.&quot;
        title=&quot;First step of creating GCP Cloud Scheduler with cron tab set to do job every 5 minutes.&quot;
        src=&quot;/static/99546cee38cbdf79d40d30511b74ec32/f058b/auth_url_1.png&quot;
        srcset=&quot;/static/99546cee38cbdf79d40d30511b74ec32/c26ae/auth_url_1.png 158w,
/static/99546cee38cbdf79d40d30511b74ec32/6bdcf/auth_url_1.png 315w,
/static/99546cee38cbdf79d40d30511b74ec32/f058b/auth_url_1.png 630w,
/static/99546cee38cbdf79d40d30511b74ec32/bad1b/auth_url_1.png 841w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Next we need to set a target. For Cloud Run use HTTP with full URL including schema. For Auth set OIDC token with created Service Account. Remember to set IAM permission Cloud Run Invoker for this Service Account in deployed service. You can read more about it in &lt;a href=&quot;https://cloud.google.com/run/docs/authenticating/service-to-service&quot;&gt;service-to-service&lt;/a&gt; auth docs.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/af24344e78d7bec06f72686221b708af/748b0/auth_url_2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 106.32911392405065%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB+ElEQVR42pVUa3OjMAzs//9j/Z5OLo9pJ4W0CW8DNhhjGbq2uRBKm7nTeBSb8UoraZ2noqbnbf0Rvm9eXg6Hw263Ox6P+/1+s9kURTGO4zAM4y/2RGSUHq7XCwBpmvZad0r5pbUmY9ZL9bhFFozAxpiaC9jgDdlcQuMXAHeGo5Sy73sLxgHXkyQBSUTgMHghmrZtmsaemoZWBtScOS+KLMvSLEvSFIHiJGFlmed5HMfwesVcE02ZLe26RsG4h6ies6ft/TckKl5kzvIcJG2HHKV7I1eYW3ZnhlEqNdUMMDBd16FImLv5wFwHHacJjDCfnx9vr6/vpxPahBDoPIigq61rm/f2o6S6NT1Nk7dgUJVdz0Unmo5VQEtHogUd6Qx770VLVUMLMOYoWh0znZQ6iKRUNP6b+TkPjBVBcErjyFBvflLVYk7oNt0prGAsPJ+vUVRzTktJreUB/uj3DEY/yrKEyLCZ9PhjCPvRzArztKGqIAghRlB6PCooCI1cZK55DTxD6YzlzjJrUC2Dd+LNIdg0L6OUtVLNcwYYo0ZaF1J5j9n4Udk5O49hVaLPKi2V5Tx42tiF53C7/XO5XG9vo6wqpMTzwiXjFWpuv4TqZpG4x4/wYnqVnHudIftiTjT7G20S0kAkUM/4P/ZXYY3KSlnx7sE/1hr8BSAfxyguabMYAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Second step of configuration of Scheduler. URL set and OIDC token.&quot;
        title=&quot;Second step of configuration of Scheduler. URL set and OIDC token.&quot;
        src=&quot;/static/af24344e78d7bec06f72686221b708af/f058b/auth_url_2.png&quot;
        srcset=&quot;/static/af24344e78d7bec06f72686221b708af/c26ae/auth_url_2.png 158w,
/static/af24344e78d7bec06f72686221b708af/6bdcf/auth_url_2.png 315w,
/static/af24344e78d7bec06f72686221b708af/f058b/auth_url_2.png 630w,
/static/af24344e78d7bec06f72686221b708af/748b0/auth_url_2.png 868w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;You can leave the retry option with default settings. After the job is created click “Run Now” and you should see “Last run result” as “Success”.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ff33a9c64682b29a9f32cdb02e13e457/bbb77/auth_url_3.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 18.9873417721519%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAkElEQVR42kWNAQrDIAxFvf8V61ZhDEqLLIlJW8WmS3WjDxHy/9M4auQfxdj3TJQSEQAIS0s2EbGamXPey992IYzeP+jSEyISonlhDH7wlscYTUKAEMK2rdM0L5GAVpHVcKYyJwC0JfbSUFXL7Lda69koJc/zcqp+qAwvfr45l6ty2jlv+mjXcRyqd9+S2k8Pv8LR5itS0FYjAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Thirs image showing successful request from Scheduler to service.&quot;
        title=&quot;Thirs image showing successful request from Scheduler to service.&quot;
        src=&quot;/static/ff33a9c64682b29a9f32cdb02e13e457/f058b/auth_url_3.png&quot;
        srcset=&quot;/static/ff33a9c64682b29a9f32cdb02e13e457/c26ae/auth_url_3.png 158w,
/static/ff33a9c64682b29a9f32cdb02e13e457/6bdcf/auth_url_3.png 315w,
/static/ff33a9c64682b29a9f32cdb02e13e457/f058b/auth_url_3.png 630w,
/static/ff33a9c64682b29a9f32cdb02e13e457/bbb77/auth_url_3.png 765w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;Case 3- my service has ingress set to internal&lt;/h4&gt;
&lt;p&gt;For this case even when we set allow unauthenticated invocation we’ll get a 403 response when trying to access the URL. Resources which are trying to access your service needs to be in the same VPC which is not possible with all GCP products. &lt;br&gt;
To read more about internal services ingress with Cloud Run visit &lt;a href=&quot;https://cloud.google.com/run/docs/securing/ingress#internal-services&quot;&gt;docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As we see in docs, we can access our service using PubSub, EventArc or Workflows.
The simplest way will be to use the previous Cloud Scheduler method with PubSub push subscription.&lt;/p&gt;
&lt;p&gt;When you set your scheduler to use PubSub your message will reach your service but with POST method instead of GET so you need to be ready to handle it.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Cloud Scheduler connected to PubSub will return Success every time if it’s properly configured so we can’t use this method to monitor the health of our service.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b8decebf8bdf85b754aee34023f680cf/bbb77/internal_url_1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 20.88607594936709%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAjUlEQVR42lWN0Q7CIAxF+f9vnPPBiNOxahkFhmzsDmLUE0JuS09RIQRmxv3+kFJyzllrX8ziBZ0Yow9hWRZ/lKmOHKhpMqeuG80oVQAiovW1P/c4xhg4RKS1Rv82PNjK7MRjjYjCYicyH0BmyDlnfNVCqaAkeiLcKXYXN0x+q6jtn1K+ea38vubGmpu8Azua5t1GsPfHAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Image showing successful request to pubsub.&quot;
        title=&quot;Image showing successful request to pubsub.&quot;
        src=&quot;/static/b8decebf8bdf85b754aee34023f680cf/f058b/internal_url_1.png&quot;
        srcset=&quot;/static/b8decebf8bdf85b754aee34023f680cf/c26ae/internal_url_1.png 158w,
/static/b8decebf8bdf85b754aee34023f680cf/6bdcf/internal_url_1.png 315w,
/static/b8decebf8bdf85b754aee34023f680cf/f058b/internal_url_1.png 630w,
/static/b8decebf8bdf85b754aee34023f680cf/bbb77/internal_url_1.png 765w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;PubSub uses push to our Cloud Run internal service. We can use OIDC token if we set Auth required for our service.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/95ab37345b1c59243efbe700ab2e129c/64639/internal_url_2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.32911392405063%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAwUlEQVR42pWQAQ6CMAxFd/9ramAqSFnZRNqC3y0aTMDoz9Z07d7azvVEl/PZn04ppeVPuaZtfF0Vcs5S0UAhEDNxT4GZsc1sAw6B2w65WWQCiZCpxf6GlcIY+QaV+AZ8l/nK8ySG4pvPf2s79zlBe+Re2ScsIkTUdbQe+xfhrns/DMf+kao5YKoqWTmkr9xXmaVR3Mv/wGDXjbxTH0dV570/HI+rSRa0MAzDmBVjhN39sKquoFKqwPh5wGUW+LB78AMhzokqbD22ZQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Image showing created pubsub resource&quot;
        title=&quot;Image showing created pubsub resource&quot;
        src=&quot;/static/95ab37345b1c59243efbe700ab2e129c/f058b/internal_url_2.png&quot;
        srcset=&quot;/static/95ab37345b1c59243efbe700ab2e129c/c26ae/internal_url_2.png 158w,
/static/95ab37345b1c59243efbe700ab2e129c/6bdcf/internal_url_2.png 315w,
/static/95ab37345b1c59243efbe700ab2e129c/f058b/internal_url_2.png 630w,
/static/95ab37345b1c59243efbe700ab2e129c/40601/internal_url_2.png 945w,
/static/95ab37345b1c59243efbe700ab2e129c/78612/internal_url_2.png 1260w,
/static/95ab37345b1c59243efbe700ab2e129c/64639/internal_url_2.png 1568w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;PubSub POST requests can reach our service and ping it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e2dca66331c563525c116d25752c2f5b/b79a5/internal_url_3.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 31.645569620253163%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAoUlEQVR42pWQ66oDMQiE9/1fdGmXJm5iNF6SVLZ/Wlg4HBlEkGE+3Qo5NqnIvSuxdPFCI1WF5q+qGT1VP0AArfFA8koxOLKzzE1sQk4pn7kqi6//1Ga+AODxPA4gZFtzzdC6+q/uzGPlnPd9D3MgBXZXFx0aiz+T1Wcp5ysBoCKp+TAbH/O33G+i4+bRECtSaXaihKhbmPlCuCjiN65+A/IGET1gLMp7p6kAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Image showing that request reached Cloud Run service set to internall traffic only&quot;
        title=&quot;Image showing that request reached Cloud Run service set to internall traffic only&quot;
        src=&quot;/static/e2dca66331c563525c116d25752c2f5b/f058b/internal_url_3.png&quot;
        srcset=&quot;/static/e2dca66331c563525c116d25752c2f5b/c26ae/internal_url_3.png 158w,
/static/e2dca66331c563525c116d25752c2f5b/6bdcf/internal_url_3.png 315w,
/static/e2dca66331c563525c116d25752c2f5b/f058b/internal_url_3.png 630w,
/static/e2dca66331c563525c116d25752c2f5b/40601/internal_url_3.png 945w,
/static/e2dca66331c563525c116d25752c2f5b/78612/internal_url_3.png 1260w,
/static/e2dca66331c563525c116d25752c2f5b/b79a5/internal_url_3.png 1372w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There are few other methods which can leverage Workflows or creating serverless connectors but I think the described one is the simplest one if you just want to ping your service from time to time.&lt;/p&gt;
&lt;h3&gt;Self rubbing…&lt;/h3&gt;
&lt;p&gt;Some say that you can go blind when you do it ( ͡° ͜ʖ ͡°) but our services should be safe. This is not the prettiest way to keep services hot but is kind of an option.&lt;/p&gt;
&lt;p&gt;Your container will receive a system event SIGTERM. From this time you have &lt;a href=&quot;https://cloud.google.com/run/docs/reference/container-contract#instance-shutdown&quot;&gt;10 seconds&lt;/a&gt; to handle it. Often you close DB connections, flush logs and traces and prepare app to close before receiving SIGKILL.&lt;/p&gt;
&lt;p&gt;Solution is to use this 10s period to do a request to itself and make service in hot state again.&lt;/p&gt;
&lt;p&gt;Using this simple Go program you can see how this can work. Again, I’m not recommending this solution but it works.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;go&quot;&gt;&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; main

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;log&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;net/http&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;os&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;os/signal&quot;&lt;/span&gt;
	&lt;span class=&quot;token string&quot;&gt;&quot;syscall&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ResponseWriter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; req &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hello\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ResponseWriter&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; req &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Request&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pong\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

	sigc &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;chan&lt;/span&gt; os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Signal&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	signal&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Notify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sigc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; syscall&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SIGTERM&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;go&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		s &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt;sigc
		fmt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;caught signal %s: selfrubbing...\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token boolean&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://selfrubtest-x2hv5vxupa-lm.a.run.app/health&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
			log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Fatalln&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HandleFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hello&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;HandleFunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/health&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; health&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ListenAndServe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;:8080&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fbf1e03ecfee5696f8f9c2344f623afc/6bfbb/selfrub.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 10.759493670886075%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAIAAADXZGvcAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAXElEQVR42iWMOQ7AIAwE8/9PpgoCTAAbcwmQYshoiylWc/UxOZeIiERlU6113gdl/G2q0qCNZWZKaY+ID621OefV+kickZDzoRRwbwgRXHiARSUq13qQ9u8ia60PCV5x2kQzMPkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Image showing that sending request to itself works&quot;
        title=&quot;Image showing that sending request to itself works&quot;
        src=&quot;/static/fbf1e03ecfee5696f8f9c2344f623afc/f058b/selfrub.png&quot;
        srcset=&quot;/static/fbf1e03ecfee5696f8f9c2344f623afc/c26ae/selfrub.png 158w,
/static/fbf1e03ecfee5696f8f9c2344f623afc/6bdcf/selfrub.png 315w,
/static/fbf1e03ecfee5696f8f9c2344f623afc/f058b/selfrub.png 630w,
/static/fbf1e03ecfee5696f8f9c2344f623afc/40601/selfrub.png 945w,
/static/fbf1e03ecfee5696f8f9c2344f623afc/78612/selfrub.png 1260w,
/static/fbf1e03ecfee5696f8f9c2344f623afc/6bfbb/selfrub.png 1514w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;As you can see there are multiple ways to keep your Cloud Run services in hot state for free or very cheap. This will make your users, other services and devops team happy. In next blog posts we’ll look at other features of Cloud Run. If you have any questions on this topic let me know in the comments :)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Google Cloud Run - serverless heaven?]]></title><description><![CDATA[So what is serverless? Server in someone’s datacenter, magical animal or easier to use services? Some of the answers are yes. Let’s dive…]]></description><link>https://byjos.dev/cloud-run-intro/</link><guid isPermaLink="false">https://byjos.dev/cloud-run-intro/</guid><pubDate>Sat, 01 Jan 2022 17:00:00 GMT</pubDate><content:encoded>&lt;h4&gt;So what is serverless? Server in someone’s datacenter, magical animal or easier to use services? Some of the answers are yes. Let’s dive into Google Cloud Run service to see how easy it is to be“cloud native” with a secure and simple deployment solution.&lt;/h4&gt;
&lt;h2&gt;What is serverless&lt;/h2&gt;
&lt;p&gt;Often serverless services mean that they are in pay as you go “subscription” allowing you, as a user, to reduce costs. If you don’t have 24/7 traffic, you are probably overspending money. Often with serverless comes other benefits such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;increased security&lt;/li&gt;
&lt;li&gt;less infrastructure maintenance&lt;/li&gt;
&lt;li&gt;ease of deployments&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First serverless service on Google Cloud Platform was App Engine which is still available as a product. It was announced and released in &lt;a href=&quot;https://medium.com/@retomeier/an-annotated-history-of-googles-cloud-platform-90b90f948920&quot;&gt;preview in 2008 then released in GA in 2011.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Serverless options on GCP&lt;/h2&gt;
&lt;p&gt;Google Cloud Platform has a broad offer of serverless services such as Firestore, Workflows or DataFlow but today we’ll talk only about so-called Compute services.&lt;/p&gt;
&lt;h3&gt;Appengine&lt;/h3&gt;
&lt;p&gt;First serverless offer on GCP. Right now it can be used in two modes: Standard and Flexible.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;background-color: rgba(255, 152, 0, 0.38)&quot;&gt;&lt;strong&gt;Standard mode&lt;/strong&gt;&lt;/span&gt; allows you to use only a set of languages but also can scale to 0 instances when there is no traffic.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;background-color: rgba(255, 152, 0, 0.38)&quot;&gt;&lt;strong&gt;Flexible mode&lt;/strong&gt;&lt;/span&gt; allows you to use a more broad set of languages and libraries but there is always one active instance.&lt;/p&gt;
&lt;p&gt;When you once create an App Engine service you are &lt;a href=&quot;https://issuetracker.google.com/issues/36878762?pli=1&quot;&gt;&lt;strong&gt;not able to change regions&lt;/strong&gt;&lt;/a&gt; and for example scale your solution globally. But in one selected region this will work flawlessly and will be able to handle huge traffic.&lt;/p&gt;
&lt;h3&gt;Cloud Functions&lt;/h3&gt;
&lt;p&gt;Functions(FaaS) was released as a solution for event-driven architectures. &lt;strong&gt;V1&lt;/strong&gt; offers support only for a selected set of programming languages. Functions are often small code portions running independently which also allow easier scalability.&lt;/p&gt;
&lt;p&gt;With &lt;strong&gt;V2 generation&lt;/strong&gt; which are based on Cloud Run you’ll be able to overcome V1 limitations and use more languages, connect to more GCP services and get better performance.&lt;/p&gt;
&lt;h3&gt;Cloud Run&lt;/h3&gt;
&lt;p&gt;Cloud Run is the latest serverless product of GCP which we’ll focus on today. It may feel like it’s connecting the best parts of two previous, easy deployment in any available region, scaling to 0 when no traffic and good performance with even up to 4vcpu and up to 16GB of RAM (in preview).&lt;/p&gt;
&lt;h2&gt;What is Cloud Run&lt;/h2&gt;
&lt;p&gt;Cloud Run is a service where you deploy your code in a Docker container using &lt;a href=&quot;https://cloud.google.com/run/docs/reference/container-contract#languages&quot;&gt;any language&lt;/a&gt; you want (there are examples of running Cobol on Cloud Run!).&lt;/p&gt;
&lt;p&gt;All containers running on Cloud Run are in a secure gVisor sandbox so not all syscalls might be accessible, but from my experience I didn’t have any problems. Recently published second generation of Cloud Run has full Linux compatibility and should support all syscalls.&lt;/p&gt;
&lt;p&gt;Your deployed container has one public port and by default gets an https url endpoint which can be additionally secured excluding external traffic or requiring service-to-service authentication. So no need to worry about setting up Let’s Encrypt certbot and any other complicated stuff.&lt;/p&gt;
&lt;p&gt;Cloud Run is connected to GCP Operations so you get Logging + Tracing in a box which makes it easier to track and measure performance of your application.&lt;/p&gt;
&lt;h2&gt;Easy deployment and security&lt;/h2&gt;
&lt;h3&gt;Deployment&lt;/h3&gt;
&lt;p&gt;As mentioned before, you need to have a Docker container to deploy it on Cloud Run Service as new Revision.&lt;/p&gt;
&lt;p&gt;Images need to be stored on GCR in any available region (Global, Europe, Asia). To push it there you can use commands like &lt;code class=&quot;language-text&quot;&gt;docker build&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;docker push&lt;/code&gt; but there are also easier ways to do it with GCP CLI.&lt;/p&gt;
&lt;p&gt;When you go to your project directory and type &lt;code class=&quot;language-text&quot;&gt;gcloud run deploy --source=./&lt;/code&gt; it will trigger the build of the container using Buildpack. When done, it will be pushed to GCR and then deployed to Cloud Run. So using just one command you can make your app live.
From what I saw this often works well but generated containers tend to be quite big. This may have changed in recent times but if you don’t want to spend time creating the best Dockerfile you can, just use it.&lt;/p&gt;
&lt;h3&gt;Security&lt;/h3&gt;
&lt;p&gt;When deployment finishes you’ll get an individual URL with SSL and blocked public access to it. This might look like &lt;code class=&quot;language-text&quot;&gt;https://gateway-&amp;lt;hash&gt;-lm.a.run.app&lt;/code&gt; and when you try to open it you’ll see error&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Error: Forbidden
Your client does not have permission to get URL / from this server.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is because by default group &lt;code class=&quot;language-text&quot;&gt;allUsers&lt;/code&gt; doesn’t have access to invoke your service. You can change this behaviour in tab &lt;strong&gt;Triggers&lt;/strong&gt; or &lt;strong&gt;Permissions&lt;/strong&gt; and add  &lt;code class=&quot;language-text&quot;&gt;allUsers&lt;/code&gt; to the IAM list with permission &lt;code class=&quot;language-text&quot;&gt;Cloud Run Invoker&lt;/code&gt;. From my experience it’s better to manage it in Permissions as changing in tab Triggers might remove previously added users, groups or service accounts.&lt;/p&gt;
&lt;p&gt;Thanks to these IAM rules you can access your application from other GCP services (not only Cloud Run) without making it accessible to everyone. This is called &lt;a href=&quot;https://cloud.google.com/run/docs/authenticating/service-to-service&quot;&gt;service-to-service&lt;/a&gt; authentication.&lt;/p&gt;
&lt;h2&gt;Next&lt;/h2&gt;
&lt;p&gt;In future posts I’ll cover more features of Cloud Run like network access control, connecting to GCP Load Balancer, streaming data with gRPC, different CPU allocations or how to keep Cloud Run always in hot state.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Hello World]]></title><description><![CDATA[This is my first post on my new webpage. I’m sure I’ll write a lot more interesting things in the future.]]></description><link>https://byjos.dev/hello-world/</link><guid isPermaLink="false">https://byjos.dev/hello-world/</guid><pubDate>Sat, 30 Oct 2021 14:14:03 GMT</pubDate><content:encoded>&lt;p&gt;This is my first post on my new webpage.&lt;/p&gt;
&lt;p&gt;I’m sure I’ll write a lot more interesting things in the future.&lt;/p&gt;</content:encoded></item></channel></rss>