<?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>DEV Community: Chuma Takahiro</title>
    <description>The latest articles on DEV Community by Chuma Takahiro (@chumaltd).</description>
    <link>https://dev.to/chumaltd</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4226108%2F244a10bf-73cf-429b-80ff-cb71d43279a2.jpg</url>
      <title>DEV Community: Chuma Takahiro</title>
      <link>https://dev.to/chumaltd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chumaltd"/>
    <language>en</language>
    <item>
      <title>Kubernetes as OS</title>
      <dc:creator>Chuma Takahiro</dc:creator>
      <pubDate>Wed, 04 Nov 2026 15:26:06 +0000</pubDate>
      <link>https://dev.to/chumaltd/kubernetes-as-os-2n8o</link>
      <guid>https://dev.to/chumaltd/kubernetes-as-os-2n8o</guid>
      <description>&lt;p&gt;Kubernetes is increasingly incorporating the functionalities of an Operating System.&lt;br&gt;&lt;br&gt;
The term "OS" is multifaceted, and the essential functions vary depending on one's perspective. For software and engineers, the critical functions are those that manage hardware components like the CPU, RAM, and disk. If these are being controlled through Kubernetes configurations, then Kubernetes can be considered an OS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Established as a Server OS
&lt;/h2&gt;

&lt;p&gt;As of 2024, widely used OSes include Windows, MacOS, and Linux, with Linux having numerous derivatives like Android.&lt;br&gt;&lt;br&gt;
These traditional OSes provide a wide range of functions to operate a single computer.&lt;/p&gt;

&lt;p&gt;Kubernetes, however, offers the ability to manage not just a single machine but multiple ones.&lt;/p&gt;

&lt;p&gt;In cloud services and data center setups, it's common to have configurations that combine multiple servers. With local area networks (LAN) becoming extremely fast, distributing processing tasks across multiple servers has become a more practical way to expand processing power than merely upgrading a single machine.&lt;/p&gt;

&lt;p&gt;At the same time, advancements in semiconductors have made even standalone machines, like personal computers, significantly more powerful. This means it is now feasible to run services, previously reserved for data centers, on a single PC.&lt;br&gt;&lt;br&gt;
Since Kubernetes can operate even on a single machine, it allows for the construction of a complete cloud service on a development PC — this simple success story extends directly to data center operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decline of Docker
&lt;/h3&gt;

&lt;p&gt;Docker is remainining an alternative at the same layer, but looking back from the future, it will likely be seen as "an implementation that existed in the early days."&lt;br&gt;&lt;br&gt;
With Google's rapid development of Kubernetes, Kubernetes reached critical mass and became the de facto standard. This is already a topic of the past, and there's little more to say about it.&lt;/p&gt;

&lt;p&gt;A few years ago, before Kubernetes distributions for development PCs were available, Docker was widely used in development environments.&lt;br&gt;&lt;br&gt;
However, as noted earlier, having the same OS for both the data center and the development machine is important. In this context, Docker is now simply an anomaly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evolving as a parasite on Linux
&lt;/h2&gt;

&lt;p&gt;Kubernetes is implemented on Linux, and many of its features are essentially Linux itself.&lt;br&gt;&lt;br&gt;
Considering Linux's history as a variant of Unix, which has gradually replaced and unified its foundations, Kubernetes can be seen as the evolved form of Unix in the long run.&lt;/p&gt;

&lt;p&gt;While Linux replaced Unix's init with &lt;a href="https://en.wikipedia.org/wiki/Systemd" rel="noopener noreferrer"&gt;systemd&lt;/a&gt;, Kubernetes provides its own method for launching programs, diverging into a separate OS.&lt;/p&gt;

&lt;p&gt;There was once a naming controversy over GNU/Linux, which made sense from an engineer's perspective. In light of this, it may be more accurate to recognize the system as GNU/Linux/Kubernetes.&lt;/p&gt;

&lt;p&gt;For instance, even now, the lingua franca of Kubernetes remains bash, continuing its lineage from Unix.&lt;br&gt;&lt;br&gt;
Open-source software, compared to proprietary commercial software, offers far more opportunities for replication, supplying symbiotic components to the evolving OS—much like mitochondria in cells.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incompatibe with Windows and Mac
&lt;/h3&gt;

&lt;p&gt;Kubernetes has already become the de facto OS in the realm of multi-machine computer networks.&lt;br&gt;&lt;br&gt;
Since Kubernetes deliberately incorporates Linux, its compatibility with Windows and Mac is limited.&lt;/p&gt;

&lt;p&gt;That said, there are tools available for Windows and Mac, and they aim to ensure basic functionality.&lt;br&gt;&lt;br&gt;
However, because Linux must be implemented as a VM, this results in a nested structure, much like a matryoshka doll. This architecture often leads to issues, particularly when attempting to use internal networks or the PC’s file system.&lt;/p&gt;

&lt;p&gt;Problems encountered with Linux VMs on Windows or MacOS may lack productive solutions.&lt;/p&gt;

&lt;p&gt;In the 2010s, Macs became popular among engineers, and I too used a MacBook Air at the time.&lt;br&gt;&lt;br&gt;
Initially, it sufficed because Unix toolchains were reasonably well integrated, but as container technologies grew in importance and incomprehensible issues increased, I eventually abandoned the Mac completely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replacing Linux's Functions
&lt;/h2&gt;

&lt;p&gt;The previous discussion outlined Kubernetes' progression as a server OS for clustered configurations, and it has already passed its initial milestones.&lt;/p&gt;

&lt;p&gt;Applications running on Kubernetes are essentially Linux applications, thus they aren't limited to server-specific software.&lt;br&gt;&lt;br&gt;
It is possible to port and run a broader range of tools on Kubernetes. Since it is primarily just a security-oriented implementation, it doesn't suffer from overheads like intermediate language runtimes, such as Java.&lt;/p&gt;

&lt;p&gt;Although there is some effort required to port applications, the rise of container technologies in the open-source community has led to the widespread availability of Dockerfile build scripts. Many of these scripts are even provided by the development projects for various tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Self-destructing Tower of Babel
&lt;/h3&gt;

&lt;p&gt;The main benefit of building applications specifically for Kubernetes on a single machine is reproducibility.&lt;br&gt;
This approach offers a solution to the problem of Linux applications that no longer run smoothly on vanilla Linux distributions.&lt;/p&gt;

&lt;p&gt;Software often introduces incompatible updates. It's common to encounter situations where App A and App B both require the same underlying library, but A depends on an older version while B relies on a newer one.&lt;br&gt;&lt;br&gt;
When there are version conflicts, one of the applications will likely fail to run.&lt;/p&gt;

&lt;p&gt;Package managers of distributions like Ubuntu, along with their development communities, handle these incompatibilities in a unified manner. However, there are limits due to the combinatorial explosion of dependencies.&lt;/p&gt;

&lt;p&gt;For example, I encountered an issue when trying to set up Python tools.&lt;br&gt;&lt;br&gt;
While Python's package manager, pip, has long allowed users to install countless libraries, the latest Ubuntu 24.04 now prevents pip installations, instead directing users to use the system's package manager, apt.&lt;/p&gt;

&lt;p&gt;When depending on apt, you lose the flexibility to select specific library versions.&lt;br&gt;&lt;br&gt;
If an application's dependencies are complex, you may need to seek alternative methods to manage them.&lt;/p&gt;

&lt;p&gt;While it's clear that using a unified package management tool reduces effort compared to juggling multiple tools, even now, some of these tools are starting to falter under the pressure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kubernetes apps are possible, but not yet simple
&lt;/h3&gt;

&lt;p&gt;After encountering the limitations of Python package management, I decided to create packages on Kubernetes. Due to the lengthy setup process, I implemented a &lt;a href="https://tekton.dev/" rel="noopener noreferrer"&gt;Tekton&lt;/a&gt; pipeline.&lt;/p&gt;

&lt;p&gt;In this case, the pipeline had already been customized for development based on a version that was known to work on the server, so it operated without any issues from the start.&lt;br&gt;&lt;br&gt;
The container images are isolated from the host OS, and in this setup, I utilized a straightforward global installation method using pip. Using package management tools provided by programming languages like pip tends to minimize issues.&lt;/p&gt;

&lt;p&gt;Moreover, as shown by the ability to reuse server-oriented images, container images continue to work seamlessly even when the hardware changes. Once you build an image, the traditional installation steps become completely unnecessary.&lt;br&gt;&lt;br&gt;
There’s a significant advantage in that you’re largely unaffected by changes to the host OS, such as during distribution upgrades.&lt;/p&gt;

&lt;p&gt;The ability to reference directories on the host Linux is easily implemented using a simple hostPath, allowing you to handle the containers similarly to native Linux applications.&lt;br&gt;&lt;br&gt;
From the perspective of the completed package, it would not be incorrect to say that &lt;u&gt;Kubernetes applications can already be run directly on Linux hosts&lt;/u&gt;.&lt;/p&gt;

&lt;p&gt;However, as there are few tools to support the setup for using applications like desktop apps or CLIs, you will need to craft these setups yourself.&lt;/p&gt;

&lt;p&gt;Additionally, attention is needed for scripts running inside the container.&lt;/p&gt;

&lt;p&gt;Although they are simply bash scripts, they need to be packed within the YAML manifest.&lt;br&gt;&lt;br&gt;
This reflects a limitation of YAML, and it’s likely an issue that will be resolved through future extensions to the Kubernetes manifest format. However, at present, this area has not been a focus, and there has been no progress since its debut.&lt;/p&gt;

&lt;p&gt;When using applications similarly to Linux applications, there is often a need to specify command-line options. In this case, you will need to define variables within the scripts inside the container and find a way to inject them from the environment.&lt;br&gt;&lt;br&gt;
Tekton provides &lt;a href="https://tekton.dev/docs/pipelines/pipelines/#using-variable-substitution" rel="noopener noreferrer"&gt;variable substitution&lt;/a&gt;, which can be specified from the CLI tool tkn. While this works, specifying lengthy parameters in tkn can be cumbersome, so I created a wrapper script &lt;a href="https://github.com/chumaltd/tkn-runner" rel="noopener noreferrer"&gt;tkn-runner&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Moving forward, I hope to see the emergence of tools designed for directly interacting with containers from the host OS.&lt;br&gt;&lt;br&gt;
Since the container interface is unlikely to change significantly, the setups created now should remain usable in the future without much hassle.&lt;/p&gt;

&lt;h2&gt;
  
  
  The era of crafting silos
&lt;/h2&gt;

&lt;p&gt;While containerization of applications has become the norm in data centers, the realm of desktop applications is still in development.&lt;/p&gt;

&lt;p&gt;As evidenced by the introduction of the snap package manager in Ubuntu, there is a rational basis for containerizing client environments like PCs.&lt;br&gt;&lt;br&gt;
Each distribution has been working toward commonizing libraries, but the reality is that they have been unable to fully resolve inconsistencies between applications, leading to the necessity of using containers alongside them.&lt;/p&gt;

&lt;p&gt;If customization is not required, it is still convenient to use the OS's standard package manager.&lt;br&gt;&lt;br&gt;
However, if you need to craft your own environment, you can leverage the standardized processes of Kubernetes on a Linux desktop.&lt;/p&gt;

</description>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Reverse Terraforming GCP Load Balancers with OpenTofu</title>
      <dc:creator>Chuma Takahiro</dc:creator>
      <pubDate>Wed, 04 Nov 2026 15:06:01 +0000</pubDate>
      <link>https://dev.to/unicornresltd/reverse-terraforming-gcp-load-balancers-with-opentofu-pl5</link>
      <guid>https://dev.to/unicornresltd/reverse-terraforming-gcp-load-balancers-with-opentofu-pl5</guid>
      <description>&lt;p&gt;GCP Load Balancers are often built using the web console or CLI, which makes backup and restoration difficult. By using &lt;a href="https://opentofu.org/" rel="noopener noreferrer"&gt;OpenTofu&lt;/a&gt; or Terraform, you can implement Infrastructure as Code (IaC) even for existing resources.&lt;/p&gt;

&lt;p&gt;By preparing an &lt;code&gt;import.tf&lt;/code&gt; like the following and running &lt;code&gt;tofu plan -generate-config-out=export.tf&lt;/code&gt;, you can export the current configuration. Since &lt;code&gt;tofu plan&lt;/code&gt; queries GCP, you must be authenticated with a user who has appropriate access rights to GCP objects via &lt;code&gt;gcloud auth application-default login&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# gcloud compute forwarding-rules list --global --uri &lt;/span&gt;
&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"projects/&amp;lt;project-id&amp;gt;/global/forwardingRules/&amp;lt;object-id&amp;gt;"&lt;/span&gt;
  &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;google_compute_global_forwarding_rule.&amp;lt;unique-name&amp;gt;
}

# gcloud compute target-https-proxies list --global --uri
import &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"projects/&amp;lt;project-id&amp;gt;/global/targetHttpsProxies/&amp;lt;object-id&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;google_compute_target_https_proxy.&amp;lt;unique-name&amp;gt;
}

# gcloud compute target-http-proxies list --global --uri
import &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"projects/&amp;lt;project-id&amp;gt;/global/targetHttpProxies/&amp;lt;object-id&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;google_compute_target_http_proxy.&amp;lt;unique-name&amp;gt;
}

# gcloud compute url-maps list --uri
import &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"projects/&amp;lt;project-id&amp;gt;/global/urlMaps/&amp;lt;object-id&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;google_compute_url_map.&amp;lt;unique-name&amp;gt;
}

# gcloud compute backend-buckets list --uri
import &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"projects/&amp;lt;project-id&amp;gt;/global/backendBuckets/&amp;lt;object-id&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;google_compute_global_backend_bucket.&amp;lt;unique-name&amp;gt;
}

# gcloud compute backend-services list --uri
import &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"projects/&amp;lt;project-id&amp;gt;/global/backendServices/&amp;lt;object-id&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;google_compute_backend_service.&amp;lt;unique-name&amp;gt;
}

# gcloud compute health-checks list --uri
import &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"projects/&amp;lt;project-id&amp;gt;/global/healthChecks/&amp;lt;object-id&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;google_compute_health_check.&amp;lt;unique-name&amp;gt;
}

# gcloud compute firewall-rules list --uri
import &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"projects/&amp;lt;project-id&amp;gt;/global/firewalls/&amp;lt;object-id&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;google_compute_firewall.&amp;lt;unique-name&amp;gt;
}

# gcloud compute ssl-certificates list --global --uri
# NOTE: TLS certificates can be used for configuration changes if managed. Unmanaged ones are hard to manage declaratively.
import &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"projects/&amp;lt;project-id&amp;gt;/global/sslCertificates/&amp;lt;object-id&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;google_compute_ssl_certificate.&amp;lt;unique-name&amp;gt;
}

# gcloud compute addresses list --global --uri
# NOTE: IP addresses are hard to manage declaratively.
import &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"projects/&amp;lt;project-id&amp;gt;/global/addresses/&amp;lt;object-id&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;google_compute_global_address.&amp;lt;unique-name&amp;gt;
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the &lt;code&gt;id&lt;/code&gt;, specify the URL of the target resource obtained with &lt;code&gt;gcloud compute &amp;lt;gcp-object-type&amp;gt; list&lt;/code&gt;. For &lt;code&gt;to&lt;/code&gt;, specify the type corresponding to the GCP object as the prefix, and provide a &lt;code&gt;&amp;lt;unique-name&amp;gt;&lt;/code&gt; for identification within OpenTofu.&lt;/p&gt;

&lt;p&gt;The exported configuration file will likely not be optimal, so refactoring is necessary. You will likely want to remove many attributes that &lt;code&gt;tofu&lt;/code&gt; specifies by default. Since the meaning of each field is not always self-evident even if concise, it's important to verify them in the reference documentation. Additionally, using &lt;code&gt;for_each&lt;/code&gt; can help consolidate blocks where only a few parameters differ, maintaining code brevity.&lt;/p&gt;

&lt;p&gt;The workflow consists of checking the definitions with &lt;code&gt;tofu plan&lt;/code&gt; and applying changes with &lt;code&gt;tofu apply&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Management Points
&lt;/h2&gt;

&lt;p&gt;As shown in the previous examples, Load Balancers have many associated objects, which can make the configuration difficult to understand later. Bundling them by purpose in OpenTofu HCL makes management easier. Especially when building multiple clusters within a project, native tools like the Cloud Console list GCP objects by type, which can obscure dependency relationships.&lt;/p&gt;

&lt;h3&gt;
  
  
  Firewalls
&lt;/h3&gt;

&lt;p&gt;Among Load Balancer related objects, firewall rule settings can be the most difficult to understand. There are prerequisites described in &lt;a href="https://docs.cloud.google.com/load-balancing/docs/firewall-rules" rel="noopener noreferrer"&gt;Firewall rules for load balancing&lt;/a&gt;. Without firewall settings, health checks will fail first. A point often not explicitly mentioned in the documentation is that actual traffic also follows these conditions. If you only permit the health check target port and don't configure settings for actual traffic on a different port, you may experience a confusing situation where the console shows everything is up, but requests time out. Since firewalls are global objects, it's almost impossible to track which cluster depends on which rule without codifying them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding &lt;code&gt;depends_on&lt;/code&gt; Blocks
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;depends_on&lt;/code&gt; blocks are useful for structuring code. These are not recognized automatically and must be added manually. You define them using the HCL names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="s"&gt;"google_compute_target_https_proxy"&lt;/span&gt; &lt;span class="s"&gt;"proxy_set"&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;depends_on&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="err"&gt;google_compute_url_map.url_map,
    google_compute_firewall.allow_hc_v&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="err"&gt;google_compute_firewall.allow_hc_v&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="err"&gt;google_compute_firewall.allow_glb_v&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="err"&gt;google_compute_firewall.allow_glb_v&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As in this example, there are constraints such as not being able to mix IPv6 and IPv4 or HTTPS and HTTP within a single object. As the Load Balancer configuration grows, defining dependencies allows &lt;code&gt;tofu plan&lt;/code&gt; to detect inconsistencies before applying changes. Furthermore, there are actual dependencies between GCP objects; requesting a build in a flat manner can result in errors due to missing prerequisite objects. &lt;code&gt;depends_on&lt;/code&gt; ensures that execution waits according to the definitions, leading to stable behavior during clean builds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Obtaining IP Addresses
&lt;/h3&gt;

&lt;p&gt;One strategy is to not manage GCP IP addresses in HCL. While they can be created with &lt;code&gt;tofu&lt;/code&gt;, IP addresses are not resources where you can "gain" a specific desired address, so the effect of declaration is weak. If you simply obtain and lock an IP address from the Cloud Console, you can just specify it in &lt;code&gt;google_compute_global_forwarding_rule.ip_address&lt;/code&gt;. If you want to obtain an ephemeral IP, specify &lt;code&gt;IPV4|IPV6&lt;/code&gt; in &lt;code&gt;google_compute_global_forwarding_rule.ip_version&lt;/code&gt;. After startup, lock it as a static IP in the Cloud Console and update the HCL accordingly. SSL certificates are handled similarly; if you are registering and updating them on GCP via an external process, you can simply reference those objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleanup after Export
&lt;/h2&gt;

&lt;p&gt;Files generated by &lt;code&gt;tofu plan -generate-config-out&lt;/code&gt; contain many fields automatically assigned by GCP and read-only attributes that do not need management in HCL. Leaving these can make the code hard to read and may cause unnecessary drifts during future provider updates.&lt;/p&gt;

&lt;p&gt;Specifically, you should review or remove the following fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt;, &lt;code&gt;self_link&lt;/code&gt;: Attributes fixed after resource creation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;creation_timestamp&lt;/code&gt;: The creation date and time.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;project&lt;/code&gt;: If configured at the provider level, it doesn't need to be specified for each resource.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fingerprint&lt;/code&gt;: Values for preventing update conflicts, often found in &lt;code&gt;backend_service&lt;/code&gt;. Not needed during initial import.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consolidating common values such as project IDs and regions into &lt;code&gt;locals&lt;/code&gt; or &lt;code&gt;variables&lt;/code&gt; makes it easier to deploy to multiple environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification and Achieving Zero-drift
&lt;/h2&gt;

&lt;p&gt;After completing the &lt;code&gt;tofu apply&lt;/code&gt; with the import blocks, immediately run a standard &lt;code&gt;tofu plan&lt;/code&gt; to verify that it shows "No changes".&lt;/p&gt;

&lt;p&gt;OpenTofu compares the actual GCP configuration with the &lt;code&gt;terraform.tfstate&lt;/code&gt; (state file), which records the state of managed resources. Since the state file plays a critical role as the "source of truth" in IaC, establishing a zero-diff state immediately after import is a fundamental prerequisite for stable long-term operation.&lt;/p&gt;

&lt;p&gt;If there are differences, the generated HCL definitions slightly mismatch the actual configuration on GCP.&lt;/p&gt;

&lt;p&gt;Be particularly careful if a resource recreation (Replace) occurs, such as &lt;strong&gt;"Plan: 1 to add, 0 to change, 1 to destroy"&lt;/strong&gt;. Recreating a Load Balancer can lead to IP address changes or service downtime. You must carefully examine the differences and adjust the HCL to match the actual configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standard Workflow Preparation
&lt;/h2&gt;

&lt;p&gt;Once IaC implementation is complete, setting up a safe operational environment for the entire team is essential. The codebase should be tracked using version control systems like Git.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;.tfstate&lt;/code&gt;: The state file (&lt;code&gt;.tfstate&lt;/code&gt;) is the only source of truth defining the current state of your system. Even if you have the HCL, losing this file means OpenTofu can no longer recognize your existing resources. This creates a severe risk where an accidental &lt;code&gt;apply&lt;/code&gt; might attempt to recreate or overwrite resources that are already in production, leading to potential collisions or unintended destruction, and requiring a dangerous, labor-intensive re-import process to recover.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;.terraform.lock.hcl&lt;/code&gt;: Pin the &lt;code&gt;google&lt;/code&gt; provider version in a &lt;code&gt;required_providers&lt;/code&gt; block and include &lt;code&gt;.terraform.lock.hcl&lt;/code&gt; in the repository to prevent unexpected behavior from provider specification changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, automatically running &lt;code&gt;tofu plan&lt;/code&gt; during pull requests via CI/CD ensures that the impact of changes is visualized beforehand and prevents unintended infrastructure changes from being mixed into production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration with Google Kubernetes Engine
&lt;/h2&gt;

&lt;p&gt;This method assumes a configuration connecting from a &lt;code&gt;backendService&lt;/code&gt; to a &lt;code&gt;Service&lt;/code&gt; with Standalone NEG. It can connect to standard Kubernetes Services and Pods, but adding annotations to the &lt;code&gt;Service&lt;/code&gt; and setting up to accept GCP health checks is necessary.&lt;/p&gt;

&lt;p&gt;This approach foregoes the adoption of Gateway API. Even if you could build using Gateway API, it is possible to export the full set of GCP objects with OpenTofu. However, in reality, there are many cases where Gateway API cannot fully support requirements—for example, it has long lacked support for housing a &lt;code&gt;backendBucket&lt;/code&gt; in the same Load Balancer. Without Gateway API, this network access layer won't be codified, necessitating the use of HCL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dual-stack NEGs
&lt;/h3&gt;

&lt;p&gt;Network Endpoint Groups are added via annotations, but the dual-stack setting is determined by the &lt;code&gt;Service&lt;/code&gt; spec. If the default is IPv4 only, the following setting allows the NEG to also accept IPv6:&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;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cloud.google.com/neg&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{"exposed_ports":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{"443":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{"name":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"web-neg"}}}'&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
  &lt;span class="na"&gt;ipFamilyPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PreferDualStack&lt;/span&gt;
  &lt;span class="na"&gt;ipFamilies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;IPv6&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;IPv4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the application within the Pod must obviously listen not only on &lt;code&gt;0.0.0.0&lt;/code&gt; but also on &lt;code&gt;[::]&lt;/code&gt;. Also, the order of &lt;code&gt;ipFamilies&lt;/code&gt; is significant.&lt;/p&gt;

</description>
      <category>gcp</category>
    </item>
    <item>
      <title>GKE のコンテナネイティブ負荷分散</title>
      <dc:creator>Chuma Takahiro</dc:creator>
      <pubDate>Wed, 04 Nov 2026 14:42:49 +0000</pubDate>
      <link>https://dev.to/chumaltd/gke-nokontenaneiteibufu-he-fen-san-4l3n</link>
      <guid>https://dev.to/chumaltd/gke-nokontenaneiteibufu-he-fen-san-4l3n</guid>
      <description>&lt;p&gt;GKE(Google Kubernetes Engine)は、HTTPS サービスを Kubernetes Gateway/Ingress を用いて公開できます。&lt;br&gt;
非 HTTP のサービスを公開するには、&lt;a href="https://cloud.google.com/load-balancing/docs/network" rel="noopener noreferrer"&gt;外部 TCP/UDP ネットワーク負荷分散&lt;/a&gt;を別途構築し Service へのルーティングを設定します。&lt;/p&gt;

&lt;p&gt;GKE は 1 クラスタで共用できますが、TCP ロードバランサは公開するポートごとに 1 つずつ追加する構成になります。&lt;br&gt;
また、HTTPS サービスであっても GCP の付加機能を利用したい場合には手動構成が必要になる場合があります。&lt;/p&gt;
&lt;h2&gt;
  
  
  NEG の作成
&lt;/h2&gt;

&lt;p&gt;リクエストを処理する Network Endpoint Group(NEG)までは、kubernetes で作成できます。&lt;/p&gt;

&lt;p&gt;Service に&lt;code&gt;cloud.google.com/neg&lt;/code&gt;アノテーションを追加すると、GCP のスタンドアロン NEG が作成されます。&lt;br&gt;
対応する Deployment などの Pod はごく普通の構成で動作します。&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;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;mail&lt;/span&gt;
  &lt;span class="na"&gt;labels&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;mail&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cloud.google.com/neg&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{"exposed_ports":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{"25":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{"name":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"mail"}}}'&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
  &lt;span class="na"&gt;selector&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;mail&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mail-smtp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;リソース状況は、&lt;code&gt;kubectl get ServiceNetworkEndpointGroups [-o yaml &amp;lt;NEG name&amp;gt;]&lt;/code&gt;コマンドで確認できます。&lt;br&gt;
NEG が不要になった場合には&lt;code&gt;kubectl delete&lt;/code&gt;で Service を削除すると同時に削除されます。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;exposed_ports&lt;/code&gt;アノテーションのポート番号には、ロードバランサーがアクセスする番号を指定する必要があります。&lt;br&gt;
TCP ロードバランサーの場合は公開するポート番号、https ロードバランサーの場合には 443 または 80 です。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;exposed_ports&lt;/code&gt;には&lt;code&gt;spec.ports.[].port&lt;/code&gt;の番号を指定するため、Pod が公開ポートと異なるポートをサーブしている場合には&lt;code&gt;targetPort&lt;/code&gt;を用いて変換する必要があります。&lt;/p&gt;
&lt;h3&gt;
  
  
  NEG 作成エラー
&lt;/h3&gt;

&lt;p&gt;なお、NEG はゾーン内で同名オブジェクトを重複作成できず、ゾーンが異なる場合には重複可能です。ゾーンはk8sクラスタのロケーションで決まります。&lt;/p&gt;

&lt;p&gt;重複など作成エラー時には、k8s Service は作成されるものの NEG が追加されない、という分かりづらい挙動になります。&lt;br&gt;
&lt;code&gt;kubectl describe service &amp;lt;service-name&amp;gt;&lt;/code&gt;を実行することでエラーログを確認できます。&lt;code&gt;Events&lt;/code&gt;欄の具体的なメッセージを解釈することが重要です。NEG の作成に失敗している場合にも、ログレベルは&lt;code&gt;WARNING&lt;/code&gt;にとどまります。&lt;/p&gt;
&lt;h2&gt;
  
  
  ロードバランサの作成
&lt;/h2&gt;

&lt;p&gt;HTTP サービスには ingress があり、GKE ingress はコンテナネイティブ負荷分散に対応しています。&lt;br&gt;
一方、TCP サービスには対応する Kubernetes サービスがなく、&lt;code&gt;gcloud compute&lt;/code&gt;コマンドで手動構築します。&lt;/p&gt;

&lt;p&gt;依存関係に沿って health check, backend service, TCP proxy, forwarding rule の順で作成します。&lt;/p&gt;
&lt;h3&gt;
  
  
  Backend service 作成
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gcloud compute health-checks create tcp &amp;lt;tcp-basic-check&amp;gt; &lt;span class="nt"&gt;--use-serving-port&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;--use-serving-port&lt;/code&gt;はサービスのポート設定を参照して監視します。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gcloud compute backend-services create &amp;lt;gke-bs&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="nt"&gt;--protocol&lt;/span&gt; TCP &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--global-health-checks&lt;/span&gt; &lt;span class="nt"&gt;--health-checks&lt;/span&gt; &amp;lt;tcp-basic-check&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--timeout&lt;/span&gt; 5m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TCP プロキシが global スコープのサービスであるため、backend service は&lt;code&gt;--global&lt;/code&gt;で作成します。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gcloud compute backend-services add-backend &amp;lt;gke-bs&amp;gt; &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network-endpoint-group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;mail&amp;gt; &lt;span class="nt"&gt;--network-endpoint-group-zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;asia-northeast1-a &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--balancing-mode&lt;/span&gt; CONNECTION &lt;span class="nt"&gt;--max-connections-per-endpoint&lt;/span&gt; 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;backend service のリージョン(global)に加えて NEG の zone も指定する必要があります。&lt;/p&gt;

&lt;h3&gt;
  
  
  TCP プロキシ作成
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gcloud compute target-tcp-proxies create &amp;lt;gke-lb-proxy&amp;gt; &lt;span class="nt"&gt;--backend-service&lt;/span&gt; &amp;lt;gke-bs&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;--proxy-header&lt;/span&gt; PROXY_V1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;IP 保持のために proxy プロトコルを使いたい場合には、&lt;code&gt;target-tcp-proxies&lt;/code&gt;作成オプションで&lt;code&gt;PROXY_V1&lt;/code&gt;を指定します。&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTPS プロキシ作成
&lt;/h3&gt;

&lt;p&gt;HTTPS サービスは Ingress などの k8s Gateway で構築でき、基本的な構成には&lt;code&gt;gcloud&lt;/code&gt;によるネットワーク構築は不要です。&lt;/p&gt;

&lt;p&gt;ロードバランサが提供する独自機能を利用したい場合には、&lt;code&gt;target-tcp-proxy&lt;/code&gt;に換えて HTTPS 向けに&lt;code&gt;target-https-proxy&lt;/code&gt;, &lt;code&gt;url-maps&lt;/code&gt;, &lt;code&gt;ssl-certificates&lt;/code&gt;のセットを作成します。&lt;br&gt;
HTTPS ロードバランサのオブジェクトは複雑であるため、とくに初回は Web コンソールから作成した方が手軽でしょう。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;url-maps&lt;/code&gt;のルーティング先が&lt;code&gt;backend-services&lt;/code&gt;を指す構成となり、NEG 経由で各 k8s Service に到達します。&lt;br&gt;
&lt;code&gt;health-checks&lt;/code&gt;と&lt;code&gt;backend-services&lt;/code&gt;, &lt;code&gt;forwarding-rules&lt;/code&gt;は TCP プロキシと共通です。&lt;/p&gt;
&lt;h3&gt;
  
  
  フォワーディング・ルール作成
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gcloud compute forwarding-rules create &amp;lt;tcp-gke-forwarding-rule&amp;gt; &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="nt"&gt;--target-tcp-proxy&lt;/span&gt; &amp;lt;gke-lb-proxy&amp;gt; &lt;span class="nt"&gt;--ports&lt;/span&gt; 25 &lt;span class="nt"&gt;--address&lt;/span&gt; &amp;lt;some-static-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;--address&lt;/code&gt;オプションは、事前に確保しておいた静的 IP を指定します。複数の転送ルールを作成する際、ポートが重複しなければ同一 IP に設定できます。&lt;/p&gt;
&lt;h2&gt;
  
  
  ルーティングオブジェクトの管理
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;target-tcp-proxy&lt;/code&gt;, &lt;code&gt;forwarding-rules&lt;/code&gt;, &lt;code&gt;backend-services&lt;/code&gt;, &lt;code&gt;health-checks&lt;/code&gt;の 4 種は GCP 独自オブジェクトです。&lt;br&gt;
これらを kubernetes のようにコードとして管理するには Terraform を利用するのが手軽です。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/unicornresltd/reverse-terraforming-gcp-load-balancers-with-opentofu-pl5"&gt;OpenTofu のエクスポート機能&lt;/a&gt;を利用することで、&lt;code&gt;gcloud&lt;/code&gt;コマンドで作成したオブジェクトをエクスポートできます。&lt;/p&gt;
&lt;h3&gt;
  
  
  クラスタ移行
&lt;/h3&gt;

&lt;p&gt;上の手順でグローバルの外部 TCP プロキシロードバランサを作成した場合、構築した 4 つの GCP オブジェクトのうち&lt;code&gt;backend-services&lt;/code&gt;が参照する NEG を変更するだけでクラスタ移行が完了します。&lt;br&gt;
プロキシはグローバルにサービス提供しているためそのまま流用でき、IP アドレスも変わりません。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;k8s の新クラスタを作成し、Service や Pod 群をデプロイ

&lt;ul&gt;
&lt;li&gt;Service マニフェストのアノテーションにより、NEG は新クラスタのゾーンに自動作成&lt;/li&gt;
&lt;li&gt;クラスタを同一ゾーンに作成すると、NEG の重複エラーになる点に注意。アノテーションの編集が必要&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backend-services&lt;/code&gt;の設定変更

&lt;ul&gt;
&lt;li&gt;gcloud または terraform を用いる&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;health-checks&lt;/code&gt;はグローバルオブジェクトであり、同一サービスならゾーンが変わっても流用できる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;terraform を使う場合、&lt;code&gt;backendServices&lt;/code&gt;の&lt;code&gt;resource.backend.group&lt;/code&gt;の URI を書き換えることで、backendServices が指す NEG を変更できます。&lt;br&gt;
次の例では、&lt;code&gt;zones&lt;/code&gt;以下を新クラスタのロケーションに合わせて変更します（該当箇所のみ抜粋）。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"google_compute_backend_service"&lt;/span&gt; &lt;span class="s2"&gt;"tfer--mail"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://www.googleapis.com/compute/v1/projects/&amp;lt;some-project-name&amp;gt;/zones/asia-northeast1-b/networkEndpointGroups/&amp;lt;NEG-name&amp;gt;"&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;編集できたら、標準手順に沿って&lt;code&gt;terraform plan&lt;/code&gt;で確認のうえ&lt;code&gt;terraform apply&lt;/code&gt;で設定できます。&lt;br&gt;
この過程で&lt;code&gt;health-checks&lt;/code&gt;も流用します。&lt;/p&gt;

&lt;p&gt;ただし、構築時の&lt;code&gt;gcloud&lt;/code&gt;オプションしだいでリージョン TCP ロードバランサも作成可能であるため、着手前に構成の特定は必須です。&lt;/p&gt;

&lt;p&gt;リージョン TCP ロードバランサの場合には、全体的に再構築が必要で、IP アドレスも変わるため最終的に DNS 設定変更で切り替えることになります。&lt;/p&gt;

</description>
      <category>gcp</category>
    </item>
  </channel>
</rss>
