<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Infrastructure 基建 &#8211; Ling&#039;s Note</title>
	<atom:link href="https://www.chunho-ling.com/category/computing/infrastructure-%e5%9f%ba%e5%bb%ba/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.chunho-ling.com</link>
	<description>Everything related IT, and me.</description>
	<lastBuildDate>Sat, 11 Apr 2026 12:41:44 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
<site xmlns="com-wordpress:feed-additions:1">104401516</site>	<item>
		<title>[Terraform] Managing Vault Secrets via Terraform and OpenTofu: A K3s Token Implementation</title>
		<link>https://www.chunho-ling.com/terraform-managing-vault-secrets-via-terraform-and-opentofu-a-k3s-token-implementation/</link>
					<comments>https://www.chunho-ling.com/terraform-managing-vault-secrets-via-terraform-and-opentofu-a-k3s-token-implementation/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Sat, 11 Apr 2026 12:41:44 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Terraform]]></category>
		<guid isPermaLink="false">https://www.chunho-ling.com/?p=1813</guid>

					<description><![CDATA[Storing and externalizing sensitive data is a foundational architectural pattern for secure platforms and applications. The following documentation demonstrates the procedure for setting and retrieving secrets within HashiCorp Vault utilizing Terraform or OpenTofu on deploying <a class="mh-excerpt-more" href="https://www.chunho-ling.com/terraform-managing-vault-secrets-via-terraform-and-opentofu-a-k3s-token-implementation/" title="[Terraform] Managing Vault Secrets via Terraform and OpenTofu: A K3s Token Implementation">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>Storing and externalizing sensitive data is a foundational architectural pattern for secure platforms and applications. The following documentation demonstrates the procedure for setting and retrieving secrets within HashiCorp Vault utilizing Terraform or OpenTofu on deploying k3s node.<span id="more-1813"></span></p>
<h2 data-path-to-node="2">1. Provider Configuration</h2>
<p data-path-to-node="3">To interact with Vault and generate secure tokens, the environment must specify the required providers.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">terraform {
  required_providers {
    vault = {
      source  = "hashicorp/vault"
    }
    random = {
      source = "hashicorp/random"
    }
  }
}</pre>
<h2 data-path-to-node="5">2. Generating the Secret Data</h2>
<p data-path-to-node="6">In this implementation, a token is required to bootstrap a K3s cluster. The <code data-path-to-node="6" data-index-in-node="76">random</code> provider is utilized to generate a secure, 32-character string.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">resource "random_password" "k3s_cluster_token" {
  length  = 32
  special = false
}</pre>
<h2 data-path-to-node="8">3. Storing Sensitive Data in Vault (Set)</h2>
<p data-path-to-node="9">The generated token is injected into Vault using the <code data-path-to-node="9" data-index-in-node="53">vault_kv_secret_v2</code> resource. This operation assumes the target Vault mount path is configured for KV Version 2.</p>
<ul data-path-to-node="10">
<li>
<p data-path-to-node="10,0,0"><b data-path-to-node="10,0,0" data-index-in-node="0">Mount Point:</b> <code data-path-to-node="10,0,0" data-index-in-node="13">home-lab-secrets</code></p>
</li>
<li>
<p data-path-to-node="10,1,0"><b data-path-to-node="10,1,0" data-index-in-node="0">Secret Path:</b> <code data-path-to-node="10,1,0" data-index-in-node="13">k3s-cluster-token</code></p>
</li>
<li>
<p data-path-to-node="10,2,0"><b data-path-to-node="10,2,0" data-index-in-node="0">Payload Format:</b> JSON encoded key-value pair.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">resource "vault_kv_secret_v2" "k3s_cluster_token" {
  mount     = "home-lab-secrets"
  name      = "k3s-cluster-token"
  data_json = jsonencode({
    token = random_password.k3s_cluster_token.result
  })
}</pre>
</li>
</ul>
<h2 data-path-to-node="12">4. Retrieving Sensitive Data from Vault (Get)</h2>
<p data-path-to-node="13">To utilize the stored secret elsewhere in the infrastructure code, a Terraform data source fetches the values from Vault. The <code data-path-to-node="13" data-index-in-node="126">depends_on</code> meta-argument ensures the secret is fully provisioned before retrieval is attempted.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">data "vault_kv_secret_v2" "k3s_cluster_token" {
  depends_on = [vault_kv_secret_v2.k3s_cluster_token]
  mount      = "home-lab-secrets"
  name       = "k3s-cluster-token"
}</pre>
<h2 data-path-to-node="15">5. Usage Example: Bootstrapping a Node</h2>
<p data-path-to-node="16">Once retrieved, the secret data can be accessed via <code data-path-to-node="16" data-index-in-node="52">data.vault_kv_secret_v2.&lt;name&gt;.data.&lt;key&gt;</code>. In the provided example, the token is passed as an environment variable (<code data-path-to-node="16" data-index-in-node="168">K3S_TOKEN</code>) over an SSH connection using a <code data-path-to-node="16" data-index-in-node="210">remote-exec</code> provisioner to join a node to the existing K3s cluster.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">provisioner "remote-exec" {
    inline = [
      "cloud-init status --wait",
      "curl -sfL https://get.k3s.io | K3S_URL='https://${local.master_node.network.ip}:6443' K3S_TOKEN='${data.vault_kv_secret_v2.k3s_cluster_token.data.token}' sh -"
    ]
  }</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/terraform-managing-vault-secrets-via-terraform-and-opentofu-a-k3s-token-implementation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1813</post-id>	</item>
		<item>
		<title>[Proxmox] Setup proxmox cluster and join node</title>
		<link>https://www.chunho-ling.com/proxmox-setup-proxmox-cluster-and-join-node/</link>
					<comments>https://www.chunho-ling.com/proxmox-setup-proxmox-cluster-and-join-node/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Thu, 10 Oct 2024 21:15:35 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Infrastructure 基建]]></category>
		<category><![CDATA[Proxmox]]></category>
		<category><![CDATA[Server 伺服器]]></category>
		<category><![CDATA[Virtualization 虛擬化]]></category>
		<guid isPermaLink="false">https://www.chunho-ling.com/?p=1740</guid>

					<description><![CDATA[It is easy to find many material on how to setup cluster, but sometime it will have variance issues when join cluster. Lesson learnt from previous work, I will conclude them into steps and hope <a class="mh-excerpt-more" href="https://www.chunho-ling.com/proxmox-setup-proxmox-cluster-and-join-node/" title="[Proxmox] Setup proxmox cluster and join node">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>It is easy to find many material on how to setup cluster, but sometime it will have variance issues when join cluster.</p>
<p>Lesson learnt from previous work, I will conclude them into steps and hope it can help others.<span id="more-1740"></span>Prerequisites</p>
<ol>
<li>Ensure all Proxmox nodes are same version.<br />
It can done by run commands in each node below:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">## Update package list.
sudo apt update

## Ensure all proxmox node in same version.
sudo apt dist-upgrade -y 

## Update package.
sudo apt upgrade

## Clean up
sudo apt clean</pre>
</li>
<li>Ensure all node connect to network;</li>
<li>Ensure all node can resolve each other&#8217;s DNS record;</li>
</ol>
<p>In there, it will use 2 nodes (nodeA, nodeB) in command as sample/</p>
<p>Steps:</p>
<ol>
<li>Create cluster.<br />
In nodeA, use command below to create cluster.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">pvecm create demo-cluster</pre>
</li>
<li>Grand cluster firewall port.<br />
In nodeA, open /etc/pve/firewall/cluster.fw , add rules inside section [RULES], sample as below:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">[RULES]

IN SSH(ACCEPT) -i vmbr0 -log nolog # SSH between nodes
IN NTP(ACCEPT) -i vmbr0 -log nolog # NTP sync time
IN DNS(ACCEPT) -i vmbr0 -log nolog # DNS resolve
IN ACCEPT -i vmbr0 -p tcp -dport 5403 -sport 5403 -log nolog # Proxmox VE Cluster Daemon
IN ACCEPT -i vmbr0 -p tcp -dport 60050 -sport 60000 -log nolog # Proxmox VE backup and migration traffic
IN ACCEPT -i vmbr0 -p udp -dport 5405 -sport 5404 -log nolog # Proxmox corosync
IN ACCEPT -i vmbr0 -p tcp -dport 3128 -sport 3128 -log nolog # Proxmox VE HA (High Availability) manager
IN ACCEPT -i vmbr0 -p tcp -dport 5999 -sport 5900 -log nolog # SPICE console connections.
IN ACCEPT -i vmbr0 -p tcp -dport 8009 -sport 8007 -log nolog # Proxmox VE cluster traffic
IN ACCEPT -i vmbr0 -p tcp -dport 8006 -sport 8006 -log nolog # Proxmox VM</pre>
</li>
<li>Join node.<br />
In nodeB, use command below to join cluster.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">pvecm add &lt;node1 IP address&gt;</pre>
</li>
<li>Verify result<br />
In nodeB, run command below, if it can found nodeB IP address, means node join successfully.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">pvecm status</pre>
<p><img data-recalc-dims="1" fetchpriority="high" decoding="async" class="alignnone size-full wp-image-1741" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/Screenshot-2024-10-09-221017.png?resize=678%2C617&#038;ssl=1" alt="" width="678" height="617" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/Screenshot-2024-10-09-221017.png?w=1021&amp;ssl=1 1021w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/Screenshot-2024-10-09-221017.png?resize=300%2C273&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/Screenshot-2024-10-09-221017.png?resize=768%2C699&amp;ssl=1 768w" sizes="(max-width: 678px) 100vw, 678px" /></li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/proxmox-setup-proxmox-cluster-and-join-node/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1740</post-id>	</item>
		<item>
		<title>[Git] Troubleshoot on unable to read tree ()</title>
		<link>https://www.chunho-ling.com/git-troubleshoot-on-unable-to-read-tree/</link>
					<comments>https://www.chunho-ling.com/git-troubleshoot-on-unable-to-read-tree/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Wed, 09 Oct 2024 20:18:54 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Git]]></category>
		<guid isPermaLink="false">https://www.chunho-ling.com/?p=1734</guid>

					<description><![CDATA[When git checkout commit, found error Fix Unable to read tree like that. It cause by dangling commit and dangling blob in repository. Dangling commit:  Commit that isn&#8217;t directly linked to by any child commit, <a class="mh-excerpt-more" href="https://www.chunho-ling.com/git-troubleshoot-on-unable-to-read-tree/" title="[Git] Troubleshoot on unable to read tree ()">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>When git checkout commit, found error Fix Unable to read tree like that.</p>
<p><img data-recalc-dims="1" decoding="async" class="alignnone size-full wp-image-1735" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/2024-10-04-15_08_56-Untitled-Paint.png?resize=678%2C204&#038;ssl=1" alt="" width="678" height="204" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/2024-10-04-15_08_56-Untitled-Paint.png?w=1127&amp;ssl=1 1127w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/2024-10-04-15_08_56-Untitled-Paint.png?resize=300%2C90&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/2024-10-04-15_08_56-Untitled-Paint.png?resize=1024%2C308&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/2024-10-04-15_08_56-Untitled-Paint.png?resize=768%2C231&amp;ssl=1 768w" sizes="(max-width: 678px) 100vw, 678px" /><span id="more-1734"></span></p>
<p>It cause by dangling commit and dangling blob in repository.</p>
<p>Dangling commit:  Commit that isn&#8217;t directly linked to by any child commit, branch, tag or other reference</p>
<p>Dangling blob: A change that made it to the staging area/index, but never got committed.</p>
<p>These dragging commit and blob can found in command below:</p>
<pre data-bidi-marker="true"><code class="language-batch">git fsck --name-objects
</code></pre>
<p>Output:</p>
<p>&nbsp;</p>
<p><img data-recalc-dims="1" decoding="async" class="alignnone size-full wp-image-1736" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/2024-10-04-15_11_51-Fix-unable-to-read-tree-__Committed-ID__-Troika-Confluence-%E2%80%94-Mozilla-Firef.png?resize=678%2C790&#038;ssl=1" alt="" width="678" height="790" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/2024-10-04-15_11_51-Fix-unable-to-read-tree-__Committed-ID__-Troika-Confluence-%E2%80%94-Mozilla-Firef.png?w=883&amp;ssl=1 883w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/2024-10-04-15_11_51-Fix-unable-to-read-tree-__Committed-ID__-Troika-Confluence-%E2%80%94-Mozilla-Firef.png?resize=257%2C300&amp;ssl=1 257w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/2024-10-04-15_11_51-Fix-unable-to-read-tree-__Committed-ID__-Troika-Confluence-%E2%80%94-Mozilla-Firef.png?resize=879%2C1024&amp;ssl=1 879w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/10/2024-10-04-15_11_51-Fix-unable-to-read-tree-__Committed-ID__-Troika-Confluence-%E2%80%94-Mozilla-Firef.png?resize=768%2C895&amp;ssl=1 768w" sizes="(max-width: 678px) 100vw, 678px" /></p>
<p>Run command below to clean danging commit / blob and clean up repository</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">cd $REPO_PATH 
## Remove all danging commit and blob and GC collect. 
git reflog expire --expire=now --all 
git gc --prune=now 

## Clean up local old / conflict branch 
git remote prune origin</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/git-troubleshoot-on-unable-to-read-tree/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1734</post-id>	</item>
		<item>
		<title>[GitHub Action] Get gradle package version</title>
		<link>https://www.chunho-ling.com/github-action-get-gradle-package-version/</link>
					<comments>https://www.chunho-ling.com/github-action-get-gradle-package-version/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Tue, 12 Mar 2024 19:59:56 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[CI / CD]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[DevOps]]></category>
		<guid isPermaLink="false">https://www.chunho-ling.com/?p=1691</guid>

					<description><![CDATA[For executing pipeline, it is common to get package version. One of the patrice is mark the package version in package info file. In this example, it will use Gradle as example to show how <a class="mh-excerpt-more" href="https://www.chunho-ling.com/github-action-get-gradle-package-version/" title="[GitHub Action] Get gradle package version">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>For executing pipeline, it is common to get package version. One of the patrice is mark the package version in package info file.</p>
<p>In this example, it will use Gradle as example to show how to get package version and call it in in other steps.<span id="more-1691"></span></p>
<p>Steps</p>
<ol>
<li>Update GitHub Action.<br />
Add steps below in GiutHub action.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">- name: Read package version
  id: get-version
  run: |
    version=$(grep -oP "version\s*=\s*'[^']+'" build.gradle | grep -oP "[^']*" | tr -d '\n' | tr -d ' ' | tr -d 'version=')
    echo "::set-output name=version::${version}"

- name: Print package version
  run: |
    echo "Testing current version."
    echo "Package version is ${{ steps.get-version.outputs.version }}"</pre>
</li>
<li>Check result<br />
Execute the pipeline to check result, expect version in build.gradle mentioned will shown.<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-full wp-image-1697" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-213059.png?resize=678%2C178&#038;ssl=1" alt="" width="678" height="178" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-213059.png?w=1700&amp;ssl=1 1700w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-213059.png?resize=300%2C79&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-213059.png?resize=1024%2C269&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-213059.png?resize=768%2C201&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-213059.png?resize=1536%2C403&amp;ssl=1 1536w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-213059.png?w=1356&amp;ssl=1 1356w" sizes="auto, (max-width: 678px) 100vw, 678px" /></li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/github-action-get-gradle-package-version/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1691</post-id>	</item>
		<item>
		<title>[GitHub Action] How to run GitHub action locally</title>
		<link>https://www.chunho-ling.com/github-action-how-to-run-github-action-locally/</link>
					<comments>https://www.chunho-ling.com/github-action-how-to-run-github-action-locally/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Mon, 11 Mar 2024 21:14:56 +0000</pubDate>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[CI / CD]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[GitHub Action]]></category>
		<guid isPermaLink="false">https://www.chunho-ling.com/?p=1693</guid>

					<description><![CDATA[For debugging pipeline, it is common to save, push and execute pipeline manually. However it is not a good idea because it might increase unnecessary commit and pull request in branch. It can be solved <a class="mh-excerpt-more" href="https://www.chunho-ling.com/github-action-how-to-run-github-action-locally/" title="[GitHub Action] How to run GitHub action locally">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>For debugging pipeline, it is common to save, push and execute pipeline manually. However it is not a good idea because it might increase unnecessary commit and pull request in branch. It can be solved by run the pipeline locally to ensure everything correct before push and execute. In this demo, it will execute GitHub action locally in Windows.</p>
<h1><span id="more-1693"></span>Prerequisites</h1>
<ol>
<li>Ensure required windows feature are installed properly.<br />
In Windows feature, ensure <strong>Hyper-V</strong>, <strong>Virtual Machine Platform</strong> and <strong>Windows Subsystem for Linux</strong> are checked, if not, tick missing items and click <strong>OK</strong> to install it. Restart computer after installed.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-full wp-image-1694" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-205423.png?resize=678%2C1219&#038;ssl=1" alt="" width="678" height="1219" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-205423.png?w=690&amp;ssl=1 690w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-205423.png?resize=167%2C300&amp;ssl=1 167w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-205423.png?resize=569%2C1024&amp;ssl=1 569w" sizes="auto, (max-width: 678px) 100vw, 678px" /></li>
<li>Ensure required packages are installed.<br />
Check docker engine install or not; install it and restart computer if missing;</li>
</ol>
<h1>Steps</h1>
<ol>
<li>Install act<br />
Execute command in Terminal below to install act. Or you can follow act user guide to install in another way.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">choco install act-cli</pre>
</li>
<li>Execute and verify<br />
Execute command in Terminal below, expected it can executed successfully if step do not required specific credentials.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">act --pull=false</pre>
<p><img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-full wp-image-1695" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-210808.png?resize=678%2C193&#038;ssl=1" alt="" width="678" height="193" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-210808.png?w=2426&amp;ssl=1 2426w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-210808.png?resize=300%2C85&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-210808.png?resize=1024%2C291&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-210808.png?resize=768%2C218&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-210808.png?resize=1536%2C436&amp;ssl=1 1536w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-210808.png?resize=2048%2C582&amp;ssl=1 2048w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2024/03/Screenshot-2024-03-11-210808.png?w=1356&amp;ssl=1 1356w" sizes="auto, (max-width: 678px) 100vw, 678px" /></li>
</ol>
<h1>Reference</h1>
<ol>
<li>act user guide, nektosact, <a href="https://nektosact.com/" target="_blank" rel="noopener">https://nektosact.com/</a></li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/github-action-how-to-run-github-action-locally/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1693</post-id>	</item>
		<item>
		<title>[GitLab] Fix issue on legacy attributes in certificate when register GitLab Runner</title>
		<link>https://www.chunho-ling.com/gitlab-fix-issue-on-legacy-attributes-in-certificate-when-register-gitlab-runner/</link>
					<comments>https://www.chunho-ling.com/gitlab-fix-issue-on-legacy-attributes-in-certificate-when-register-gitlab-runner/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Fri, 19 Jan 2024 21:15:47 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[GitLab]]></category>
		<category><![CDATA[Infrastructure 基建]]></category>
		<category><![CDATA[Revision Control]]></category>
		<guid isPermaLink="false">https://www.chunho-ling.com/?p=1682</guid>

					<description><![CDATA[When try to register GitLab runner with command gitlab-runner register : gitlab-runner register : tls: failed to verify certificate: x509: certificate relies on legacy Common Name field, use SANs instead. It caused by GitLab not <a class="mh-excerpt-more" href="https://www.chunho-ling.com/gitlab-fix-issue-on-legacy-attributes-in-certificate-when-register-gitlab-runner/" title="[GitLab] Fix issue on legacy attributes in certificate when register GitLab Runner">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>When try to register GitLab runner with command gitlab-runner register : gitlab-runner register : tls: failed to verify certificate: x509: certificate relies on legacy Common Name field, use SANs instead.</p>
<p>It caused by GitLab not support cert verify with legacy certificate attribute. To resolve that problem it need to genearate certificate in server again. And steps will show as below.<span id="more-1682"></span></p>
<ol>
<li>Generate new certificate and install in GitLab server<br />
Execute command below in GitLab server:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">export HOSTNAME=home-gitlb-sr01
export CERT_VALID_DAYS=36500
export CERT_PATH=/etc/gitlab/ssl

## Install OpenSSL
sudo apt install -y openssl

## Generate RSA key with 2048 length.
sudo openssl genrsa -out ${HOSTNAME}.key 2048

## Generate x509 certificate which contain SANs with key generated. 
sudo openssl req -new -x509 -addext "subjectAltName = DNS:localhost,DNS:${HOSTNAME}" -days ${CERT_VALID_DAYS} -key ${HOSTNAME}.key -out ${HOSTNAME}.crt

## Backup original certificate and replace with generated one.
sudo tar -czvf ${CERT_PATH} ${CERT_PATH}.tar.gz
sudo cp ${HOSTNAME}.crt ${CERT_PATH}/

## Restart GitLab server to apply new certificate.
sudo gitlab-ctl reconfigure
sudo gitlab-ctyl restart</pre>
</li>
<li>Import certificate in Gitlab Runner and apply settings.
<pre class="EnlighterJSRAW" data-enlighter-language="generic">export HOSTNAME=home-gitlb-sr01

## Get Cert from GitLab server and copy to runner cert directory.
openssl s_client -showcerts -connect ${HOSTNAME}:443 -servername ${HOSTNAME} &lt; /dev/null 2&gt;/dev/null | openssl x509 -outform PEM &gt; ${HOSTNAME}.crt
sudo cp ${HOSTNAME}.crt /etc/gitlab-runner/certs/

sudo gitlab-runner register --tls-ca-file=${HOSTNAME}.crt
sudo gitlab-runner restart
sudo gitlab-runner run</pre>
<p>&nbsp;</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/gitlab-fix-issue-on-legacy-attributes-in-certificate-when-register-gitlab-runner/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1682</post-id>	</item>
		<item>
		<title>[Cloud Design Pattern] Anti-corruption Layer</title>
		<link>https://www.chunho-ling.com/cloud-design-pattern-anti-corruption-layer/</link>
					<comments>https://www.chunho-ling.com/cloud-design-pattern-anti-corruption-layer/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Mon, 21 Nov 2022 19:54:55 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Design Pattern]]></category>
		<category><![CDATA[Infrastructure 基建]]></category>
		<category><![CDATA[System Design 系統設計]]></category>
		<guid isPermaLink="false">https://www.chunho-ling.com/?p=1627</guid>

					<description><![CDATA[Anti-corruption Layer is one of the design pattern to enable application communicate with external system. Problem For some reasons, some of the services cannot use common method to communicate and it cannot be change due <a class="mh-excerpt-more" href="https://www.chunho-ling.com/cloud-design-pattern-anti-corruption-layer/" title="[Cloud Design Pattern] Anti-corruption Layer">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>Anti-corruption Layer is one of the design pattern to enable application communicate with external system.<span id="more-1627"></span></p>
<h1>Problem</h1>
<p>For some reasons, some of the services cannot use common method to communicate and it cannot be change due to their own constrains. However, application still need to get resource and execute command from it. It is require to convert the response and executed result to application compatible format.</p>
<p>It will be time consuming if each service implement it&#8217;s own logic to communicate such &#8220;out-standing&#8221; service. Also, it will be more complicate on change when such system and it will impact to all involved services.</p>
<h1>Solution</h1>
<p>Implement the middle layer between services which role as a middleman to:</p>
<ol>
<li>Collect consumer request;</li>
<li>Transform request format / communication channel and send to target system;</li>
<li>Receive target system response;</li>
<li>Transform response format / communication channel and send back to consumer;</li>
</ol>
<p><img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1628" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/design_pattern-anti-corruption-layer.drawio.png?resize=300%2C91&#038;ssl=1" alt="" width="300" height="91" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/design_pattern-anti-corruption-layer.drawio.png?resize=300%2C91&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/design_pattern-anti-corruption-layer.drawio.png?resize=768%2C234&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/design_pattern-anti-corruption-layer.drawio.png?w=791&amp;ssl=1 791w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>Anti-corruption layer is the middleman which do tasks above. When the target system change, it can eliminate the change scale by only need to update anti-corruption layer, consumer do not need to update in their side.</p>
<h1>Use case</h1>
<ol>
<li>Communicate with legacy or specific protocol (e.g. SOAP, HL7, etc)</li>
<li>Communicate with legacy channel (e.g. COM / RPC call, etc)</li>
</ol>
<h1>Implementation</h1>
<h1>Consideration</h1>
<p>Compare with façade and adapter</p>
<p>Façade is set of interface and adapter is a converter between different system.</p>
<p>Anti-corruption layer combine the characteristic of façade and adapter, it provides the interfaces / event handlers to collect request and send out response between target system; In addition, anti-corruption layer contains a certain logics to translate the content to fulfill each others needs;</p>
<p>Compare with Ambassador</p>
<p>Ambassador is focus on non-fictional requirement, and anti-corruption layer is a sort of converter, so certain business logic might contain in there.</p>
<h1>Reference</h1>
<ol>
<li>Anti-corruption Layer, Microsoft Azure<br />
<a href="https://learn.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer" target="_blank" rel="noopener">https://learn.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer</a></li>
<li>The Anti-Corruption Layer Pattern, Ahmed Shirin, Dev.to<br />
<a href="https://dev.to/asarnaout/the-anti-corruption-layer-pattern-pcd" target="_blank" rel="noopener">https://dev.to/asarnaout/the-anti-corruption-layer-pattern-pcd</a></li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/cloud-design-pattern-anti-corruption-layer/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1627</post-id>	</item>
		<item>
		<title>[Virtualization] XCP-NG</title>
		<link>https://www.chunho-ling.com/xcp-ng/</link>
					<comments>https://www.chunho-ling.com/xcp-ng/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Fri, 18 Nov 2022 13:32:32 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Infrastructure 基建]]></category>
		<category><![CDATA[Virtualization 虛擬化]]></category>
		<guid isPermaLink="false">https://www.chunho-ling.com/?p=1622</guid>

					<description><![CDATA[It is common on deploy application in cloud platform. However, for some business reason (e.g. cost, security, legal, hardware constrain, etc), virtualization on premises still have its value. XCP-ng is free and open source edition <a class="mh-excerpt-more" href="https://www.chunho-ling.com/xcp-ng/" title="[Virtualization] XCP-NG">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>It is common on deploy application in cloud platform. However, for some business reason (e.g. cost, security, legal, hardware constrain, etc), virtualization on premises still have its value.</p>
<p>XCP-ng is free and open source edition of XenServer, which focked from Citrix since 2018. As inherited from XenServer, it is type 1 hypervisor so it can utilize hardware resources.</p>
<p><span id="more-1622"></span></p>
<p>XCP-ng combine with 4 major components: Computed, Network, Storage and API. The UI need to install separate Xen-Orchesta (XOA) VM, which role as a controller which similar VMWare vCenter. In XOA, it also integrate XOSAN for storage management. Also, to secure access, XCP-ng Center enables administrators to manage hypervisers via desktop applicaition.</p>
<p>Unfortunately, It is not fully support IaC (Infrastructure as Code). There has unofficial provider in Terraform registry. As it is not XCP-ng clould still in process, hopefully it will have official IaC solution once go live.</p>
<p>Reference</p>
<ol>
<li>XCP-ng.org<br />
<a href="https://xcp-ng.org/" target="_blank" rel="noopener">https://xcp-ng.org/</a></li>
<li>XCP, GitHub<br />
<a href="https://github.com/xcp-ng/xcp" target="_blank" rel="noopener">https://github.com/xcp-ng/xcp</a></li>
<li>XOA, Xen Orchestra<br />
<a href="https://xen-orchestra.com/#!/xo-home" target="_blank" rel="noopener">https://xen-orchestra.com/#!/xo-home</a></li>
<li>Xen Orchestra Provider, Terraform Registry<br />
<a href="https://registry.terraform.io/providers/terra-farm/xenorchestra/latest/docs" target="_blank" rel="noopener">https://registry.terraform.io/providers/terra-farm/xenorchestra/latest/docs</a></li>
<li>XCP-ng Center, GitHub<br />
<a href="https://github.com/xcp-ng/xenadmin" target="_blank" rel="noopener">https://github.com/xcp-ng/xenadmin</a></li>
</ol>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/xcp-ng/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1622</post-id>	</item>
		<item>
		<title>[Java] Resolve issue on escape character show when using LogstashEncoder</title>
		<link>https://www.chunho-ling.com/java-resolve-issue-on-escape-character-show-when-using-logstashencoder/</link>
					<comments>https://www.chunho-ling.com/java-resolve-issue-on-escape-character-show-when-using-logstashencoder/#respond</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Wed, 16 Nov 2022 12:41:05 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Logstash]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">https://www.chunho-ling.com/?p=1618</guid>

					<description><![CDATA[When passing data to LogStash, it will show escape character in log message. But sometime, it cannot update logstash pipeline to replace specific character so need to implement in code level. This problem caused by <a class="mh-excerpt-more" href="https://www.chunho-ling.com/java-resolve-issue-on-escape-character-show-when-using-logstashencoder/" title="[Java] Resolve issue on escape character show when using LogstashEncoder">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>When passing data to LogStash, it will show escape character in log message. But sometime, it cannot update logstash pipeline to replace specific character so need to implement in code level.</p>
<p><span id="more-1618"></span>This problem caused by escape character found in String. As LogstashEncoder will serialize object to JSON, it will replace escape ASCII character to encoded value (e.g. new line =&gt; \n).</p>
<p><img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1619" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_31_48-Window.png?resize=300%2C99&#038;ssl=1" alt="" width="300" height="99" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_31_48-Window.png?resize=300%2C99&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_31_48-Window.png?resize=1024%2C339&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_31_48-Window.png?resize=768%2C254&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_31_48-Window.png?w=1375&amp;ssl=1 1375w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>To resolve it, it can use CharacterEscapesJsonFactoryDecorator in log settings file (e.g. log4j.xml) to override specific ASCII code and replaced by defined value.</p>
<p>This example will replace string to empty string.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic"> &lt;appender name="console-json" class="ch.qos.logback.core.ConsoleAppender"&gt;
        &lt;encoder class="net.logstash.logback.encoder.LogstashEncoder" &gt;
            &lt;jsonFactoryDecorator class="net.logstash.logback.decorate.CharacterEscapesJsonFactoryDecorator"&gt;
                &lt;escape&gt;
                    &lt;!-- ASCII 10 =&gt; new line  --&gt;
                    &lt;targetCharacterCode&gt;10&lt;/targetCharacterCode&gt;
                    &lt;escapeSequence&gt;&lt;/escapeSequence&gt;
                &lt;/escape&gt;
            &lt;/jsonFactoryDecorator&gt;
        &lt;/encoder&gt;
&lt;/appender&gt;</pre>
<p>Test result:</p>
<p><img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1620" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_38_27-Window.png?resize=300%2C139&#038;ssl=1" alt="" width="300" height="139" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_38_27-Window.png?resize=300%2C139&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_38_27-Window.png?resize=1024%2C474&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_38_27-Window.png?resize=768%2C355&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_38_27-Window.png?resize=1536%2C711&amp;ssl=1 1536w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_38_27-Window.png?w=1846&amp;ssl=1 1846w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/11/2022-11-16-12_38_27-Window.png?w=1356&amp;ssl=1 1356w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/java-resolve-issue-on-escape-character-show-when-using-logstashencoder/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1618</post-id>	</item>
		<item>
		<title>[Kubernetes] Install Kubernetes in Ubuntu Linux</title>
		<link>https://www.chunho-ling.com/kubernetes-install-kubernetes-in-ubuntu-linux/</link>
					<comments>https://www.chunho-ling.com/kubernetes-install-kubernetes-in-ubuntu-linux/#comments</comments>
		
		<dc:creator><![CDATA[C.H. Ling]]></dc:creator>
		<pubDate>Sun, 07 Aug 2022 19:25:48 +0000</pubDate>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Infrastructure 基建]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Server 伺服器]]></category>
		<category><![CDATA[Virtualization 虛擬化]]></category>
		<guid isPermaLink="false">https://www.chunho-ling.com/?p=1583</guid>

					<description><![CDATA[There are different platforms to run Kubernetes (K8S) nowadays. In cloud, we can consider AWS Elastic Kubernetes Service, Azure Kubernetes Service, or we can install Talos in on-premise infrastructure as quick win solution. However, actually <a class="mh-excerpt-more" href="https://www.chunho-ling.com/kubernetes-install-kubernetes-in-ubuntu-linux/" title="[Kubernetes] Install Kubernetes in Ubuntu Linux">[...]</a>]]></description>
										<content:encoded><![CDATA[<p>There are different platforms to run Kubernetes (K8S) nowadays. In cloud, we can consider AWS Elastic Kubernetes Service, Azure Kubernetes Service, or we can install <a href="https://www.talos.dev/" target="_blank" rel="noopener">Talos</a> in on-premise infrastructure as quick win solution. However, actually we can install K8S in different Linux distributions. <span id="more-1583"></span> This article will step by step on how to install Kubernetes 1.24.3 in Ubuntu 22.04 with 1 master node and 1 worker node. Since 1.22, platform K8S not support docker swarm and switch to containerd since 1.22, so there has a sigh different during installation. That why I wrote this page for recording.</p>
<p>Steps</p>
<ol>
<li>Enable kernal modules for containerd.<br />
In shell, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">sudo cat &lt;&lt; EOF | sudo tee /etc/modules-load.d/containerd.conf 
overlay 
br_netfilter 
EOF
sudo modprobe overlay
sudo modprobe br_netfilter</pre>
</li>
<li>Initialize system settings for K8S networking.<br />
In shell, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">sudo cat &lt;&lt;EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sudo sysctl --system</pre>
</li>
<li>Prepare applications to use in following steps.<br />
In shell, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">sudo apt update
sudo apt install -y apt-transport-https curl</pre>
</li>
<li>Disable swap in OS.<br />
In shell, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab</pre>
</li>
<li>Install containerd<br />
In shell, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">sudo apt install -y ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update
sudo apt install -y containerd.io</pre>
</li>
<li>Configure containerd<br />
In shell, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">sudo mkdir -p /etc/containerd 
sudo containerd config default | sudo tee /etc/containerd/config.toml 
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml &amp;&amp; grep 'SystemdCgroup' -B 11 /etc/containerd/config.toml
sudo systemctl enable --now containerd
sudo systemctl restart containerd</pre>
</li>
<li>Install K8S<br />
In shell, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat &lt;&lt; EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt update
sudo apt install -y kubelet=$KUBERNETES_VERSION kubectl=$KUBERNETES_VERSION kubeadm=$KUBERNETES_VERSION
sudo apt-mark hold kubelet kubeadm kubectl
sudo systemctl enable --now kubelet</pre>
</li>
<li>[For Master node only] Initialize K8S cluster.<br />
In shell, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">sudo kubeadm init --pod-network-cidr $POD_NETWORK_CIDR --kubernetes-version $KUBERNETES_VERSION</pre>
</li>
<li>[For Master node only] Setup master node local settings.<br />
In shell, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config</pre>
</li>
<li>[For Master node only] Setup Calico.<br />
In shell, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml</pre>
</li>
<li>[For Master node only] Generate command for worker nodes joining cluster.<br />
In shell, execute command below.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">kubeadm token create --print-join-command</pre>
<p>It should be generate command like this, copy it to clipboard.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1584" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/untitle-1.png?resize=300%2C56&#038;ssl=1" alt="" width="300" height="56" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/untitle-1.png?resize=300%2C56&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/untitle-1.png?resize=1024%2C190&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/untitle-1.png?resize=768%2C142&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/untitle-1.png?resize=1536%2C285&amp;ssl=1 1536w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/untitle-1.png?resize=2048%2C380&amp;ssl=1 2048w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/untitle-1.png?w=1356&amp;ssl=1 1356w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
<li>[For Worker node only] Join K8S cluster.<br />
In shell, execute command which copied from previous steps.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1585" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/Untitled-2.png?resize=300%2C96&#038;ssl=1" alt="" width="300" height="96" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/Untitled-2.png?resize=300%2C96&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/Untitled-2.png?resize=1024%2C328&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/Untitled-2.png?resize=768%2C246&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/Untitled-2.png?resize=1536%2C492&amp;ssl=1 1536w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/Untitled-2.png?resize=2048%2C656&amp;ssl=1 2048w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/Untitled-2.png?w=1356&amp;ssl=1 1356w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
<li>Verify result.<br />
In master node shell, execute command below</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">kubectl get po -A -o wide</pre>
<p>Expected it will show all namespace pods and its deployed pod.<br />
<img data-recalc-dims="1" loading="lazy" decoding="async" class="alignnone size-medium wp-image-1586" src="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/WindowsTerminal_EobFLboirK.png?resize=300%2C78&#038;ssl=1" alt="" width="300" height="78" srcset="https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/WindowsTerminal_EobFLboirK.png?resize=300%2C78&amp;ssl=1 300w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/WindowsTerminal_EobFLboirK.png?resize=1024%2C266&amp;ssl=1 1024w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/WindowsTerminal_EobFLboirK.png?resize=768%2C199&amp;ssl=1 768w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/WindowsTerminal_EobFLboirK.png?resize=1536%2C398&amp;ssl=1 1536w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/WindowsTerminal_EobFLboirK.png?resize=2048%2C531&amp;ssl=1 2048w, https://i0.wp.com/www.chunho-ling.com/wp-content/uploads/2022/08/WindowsTerminal_EobFLboirK.png?w=1356&amp;ssl=1 1356w" sizes="auto, (max-width: 300px) 100vw, 300px" /></li>
</ol>
<p>Related shell script has been push in <a href="https://github.com/smling/terraform-vmware-esxi-kubernaters/tree/main/esxi-k8s-module/scripts/1.24.3" target="_blank" rel="noopener">GitHub</a> repository.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.chunho-ling.com/kubernetes-install-kubernetes-in-ubuntu-linux/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1583</post-id>	</item>
	</channel>
</rss>
