上一篇文章介紹了一個輕量級的 Kubernetes 發行版本 - k3s 。
這篇文章,我們將透過使用以下幾個 IaC(Infrastructure as Code)工具,在本地環境(例如你的 Linux 工作臺)自動化部署一個可用的 K3S 叢集
Packer - HashiCorp 開源的一個系統映象構建工具。
Terraform - HashiCorp 開源的基礎設施及程式碼自動化管理工具。
Ansible - RedHat贊助的一個開源社群專案,IT自動化配置工具。
環境需求
本演示將的所有操作將在一臺支援虛擬化(kvm + qemu + libvirt) Linux 主機上執行。
在 Ubuntu 上啟用虛擬化環境,請參考 KVM hypervisor: a beginner‘s guide 。
在 Fedora 上啟用虛擬化環境,請參考 Getting startyed with virtualization (libvirt) 。
在 openSUSE 上啟用虛擬化環境,請參考 Virtualization Guide 。
其他 Linux 發行版,請參考相關文件。
我是在我的膝上型電腦上執行的操作,系統是 openSUSE Leap 15。4 。
除了上述的虛擬化需求外,還需要在系統上安裝上面提到的幾個工具。如果你的環境中有 LinuxBrew,則可透過 Brew 直接安裝
❯ brew install packer terraform ansible
否則,請下載各自官方釋出的二進位制包,解壓後放到
PATH
路徑中。
❯ packer versionPacker v1。8。3❯ terraform versionTerraform v1。3。2on linux_amd64❯ ansible ——versionansible [core 2。13。4]
因為本示例中,使用了 Terraform 的 ansbile provisioner,因此還需要安裝這個外掛
❯ mkdir -p ~/。terraform。d/plugins❯ curl -sL \ https://raw。githubusercontent。com/radekg/terraform-provisioner-ansible/master/bin/deploy-release。sh \ ——output /tmp/deploy-release。sh❯ chmod +x /tmp/deploy-release。sh❯ /tmp/deploy-release。sh -v 2。5。0❯ rm -rf /tmp/deploy-release。sh
完成以上需求之後,我們將開始執行如下步驟
使用 Packer 建立一個基於 Debian 11。5。0 的虛擬機器系統模板映象,該映象中,將會配置好 SSH 免密登陸金鑰。
使用 Terraform 在本地虛擬環境中,創建出需要的虛擬機器,並生成後續 ansible 配置虛擬機器需要的 inventory 檔案。
使用 Ansible 配置虛擬機器節點安裝 k3s 叢集,以及演示應用。
以上所有步驟的程式碼在 (https://github。com/mengzyou/i。。。)
將程式碼克隆到本地
❯ git clone https://github。com/mengzyou/iac-examples。git❯ cd iac-example/k3scluster/
建立虛擬機器映象
首先我們需要透過 Packer 建立一個虛擬機器系統映象,後續需要使用該映象來建立虛擬機器例項,需要的程式碼在
k3scluster/packer/
目錄下
❯ cd packer/❯ tree 。|—— Makefile|—— base。pkr。hcl`—— preseed |—— debian11。txt
這裡透過 Makefile 來呼叫 packer 進行映象的構建,和上傳到虛擬化環境,注意以下變數配置
LIBVIRT_HYPERVISOR_URI := “qemu:///system”LIBVIRT_TEMPLATES_IMAGES_POOL := “templates”LIBVIRT_TEMPLATES_IMAGES_POOL_DIR := “/var/lib/libvirt/images/templates”LIBVIRT_IMAGE_NAME := “debian11-5。qcow2”ROOT_PASSWORD := “rootPassword”$(eval SSH_IDENTITY=$(shell find ~/。ssh/ -name ’id_*‘ -not -name ’*。pub‘ | head -n 1))
預設使用
${HOME}/。ssh/id_rsa
的金鑰對作為 SSH 免密訪問的金鑰,如果沒有,請先建立一個。
執行
make image
進行映象的構建,以及在本地虛擬化環境建立名為
templates
的儲存池,並將映象上傳到該儲存池中,命名為
debian11-5.qcow2
的卷,具體的程式碼,請檢視
Makefile
。
❯ make image。。。
完成之後,我們可以透過
virsh
命令檢視映象卷
❯ sudo virsh vol-list ——pool templates 名稱 路徑———————————————————————————————————— debian11-5。qcow2 /var/lib/libvirt/images/templates/debian11-5。qcow2
補充
: 在檔案
base。pkr。hcl
中,對 iso 檔案源的配置
iso_url = “https://mirrors。ustc。edu。cn/debian-cd/current/amd64/iso-cd/debian-11。5。0-amd64-netinst。iso”
配置網路地址時,在 packer 進行構建時,可能會下載 iso 檔案超時而導致構建失敗。可透過預先下載對應的 iso 檔案到本地檔案系統,然後將
iso_url
配置為本地路徑,例如
iso_url = “/data/debian-11。5。0-amd64-netinst。iso”
這樣可以避免由於網路問題導致構建失敗。
建立虛擬機器例項
接下來,我們將使用 Terraform 建立並初始化叢集所需要的虛擬機器例項,進入
k3scluster/terraform/
目錄
❯ cd 。。/terraform/
該目錄下包含了建立叢集所需虛擬機器資源的定義,首先看
provider。tf
檔案
terraform { required_providers { libvirt = { source = “dmacvicar/libvirt” version = “0。7。0” } } required_version = “>= 0。13”}provider “libvirt” { uri = var。libvirt_uri}
因為我們需要透過 libvirt 建立虛擬機器,因此這裡需要 dmacvicar/libvirt 的 Provider,該 Provider 的 uri 配置為變數
var。libvirt_uri
,預設為
qemu:///system
,也就是本地虛擬環境。
其他需要的變數定義都放在
variables。tf
檔案中。資原始檔
vms。tf
定義了需要建立的資源,其中包括
resource “libvirt_network” “network” { name = var。net_name mode = “nat” domain = var。net_domain addresses = [var。subnet] dhcp { enabled = true } dns { enabled = true local_only = true }}
建立一個 NAT 模式的虛擬網路,預設的網路地址為
192。168。123。0/24
,可透過變數
net_domain
修改。
resource “libvirt_volume” “disk” { count = length(var。vms) name = “${var。vms[count。index]。name}。qcow2” pool = “default” base_volume_name = var。template_img base_volume_pool = var。templates_pool}
根據變數
vms
定義的虛擬機器例項,建立虛擬機器的系統磁碟,基於變數
templates_pool
和
template_image
指定的模板映象,預設也就是上面我們透過 Packer 建立的系統映象。
resource “libvirt_domain” “vm” { count = length(var。vms) name = var。vms[count。index]。name autostart = true qemu_agent = true vcpu = lookup(var。vms[count。index], “cpu”, 1) memory = lookup(var。vms[count。index], “memory”, 512)。。。 }}
libvirt_domain
資源定義了需要建立的虛擬機器例項,並透過
ansible provisioner
進行是初始化配置(配置靜態IP地址和主機名)。
resource “local_file” “ansible_hosts” { content = templatefile(“。/tpl/ansible_hosts。tpl”, { vms = var。vms subnet = var。subnet gateway = cidrhost(var。subnet, 1) mask = cidrnetmask(var。subnet) nameserver = cidrhost(var。subnet, 1) user = var。user }) filename = “。。/ansible/k3s_hosts” file_permission = 0644 directory_permission = 0755}
該資源定義透過模板檔案建立虛擬機器例項的 Ansible Inventory 檔案,便於下一步透過 Ansible 進行 K3S 叢集的建立。
在應用之前,我們需要配置
vms
變數,來指定我們需要的虛擬機器例項資訊
❯ cp 。k3svms。tfvars k3dcluster。auto。tfvars
vms = [ { name = “control” cpu = 1 memory = 1024 ip = 10 groups = [“k3s”] vars = { role = “server” } }, { name = “worker1” cpu = 1 memory = 1024 ip = 21 groups = [“k3s”] vars = { role = “agent” } }, { name = “worker2” cpu = 1 memory = 1024 ip = 22 groups = [“k3s”] vars = { role = “agent” } }]
上面定義了3臺例項,1臺作為k3s叢集的 server 節點,2臺作為k3s叢集的 role 節點,預設IP地址將會被配置為
control : 192。168。123。10
worker1 : 192。168。123。21
worker2 : 192。168。123。22
接下來我們將執行 Terrform 操作
❯ terraform init❯ terraform plan ❯ terrafrom apply ——auto-approve。。。Apply complete! Resources: 8 added, 0 changed, 0 destroyed。Outputs:vms_ip_addresses = { “control” = “192。168。123。10” “worker1” = “192。168。123。21” “worker2” = “192。168。123。22”}
完成之後,3臺虛擬機器將會建立並執行,同時在
k3scluster/ansible/
目錄中將建立名為
k3s_hosts
的 Inventory 檔案。
部署K3S叢集
完成虛擬機器的建立之後,我們進入
k3scluster/ansible/
目錄,進行下一步操作
❯ cd 。。/ansible/❯ ls apps。yml init。yml k3s。yaml k3s_hosts main。yml roles
其中檔案
k3s_hosts
是在上一步生成的 Inventory 檔案,
init。yml
檔案是初始化節點的 playbook,在上一步的 Terraform 應用中以及執行了。
main。yml
檔案是安裝配置 K3S 叢集的 playbook,
roles/
目錄包含了所有的任務。
在執行具體任務之前,我們可以透過 ansbile 測試下虛擬機器節點的可用性
❯ ansible -i k3s_hosts all -m pingworker1 | SUCCESS => { “changed”: false, “ping”: “pong”}worker2 | SUCCESS => { “changed”: false, “ping”: “pong”}control | SUCCESS => { “changed”: false, “ping”: “pong”}
接下來執行
main。yml
playbook
❯ ansible-playbook -i k3s_hosts main。yml。。。PLAY RECAP ********************************************control : ok=16 changed=7 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0 worker1 : ok=8 changed=4 unreachable=0 failed=0 skipped=6 rescued=0 ignored=0 worker2 : ok=8 changed=4 unreachable=0 failed=0 skipped=6 rescued=0 ignored=0
這將會呼叫
roles/k3s/
裡定義的任務,安裝和配置 K3S 叢集,具體的執行任務,請檢視 roles 裡的程式碼。
成功之後,會發現在當前目錄生成了一個
k3s。yaml
的檔案,這是從 control 節點獲取的 kubeconfig 檔案,我們需要替換一下 api-server 的 IP
❯ sed -i ’s/127。0。0。1/192。168。123。10/g‘ k3s。yaml
之後,我們就可以透過該 kubeconfig 檔案來訪問該叢集了,例如
❯ kubectl ——kubeconfig k3s。yaml cluster-infoKubernetes control plane is running at https://192。168。123。10:6443CoreDNS is running at https://192。168。123。10:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxyMetrics-server is running at https://192。168。123。10:6443/api/v1/namespaces/kube-system/services/https:metrics-server:https/proxy❯ kubectl ——kubeconfig k3s。yaml get noNAME STATUS ROLES AGE VERSIONworker2。k3s。local Ready
至此,我們就完成了一個 K3S 叢集的部署,並可以在部署其他應用。最後,我們也可以繼續使用 ansible 來部署演示應用。
檔案
apps。yml
是部署演示應用的 playbook,其透過
roles/k3s-app/
任務,與 k3s server 節點互動來進行應用部署,其會部署 Traefik Ingress 和一個 whoami web 應用,直接執行
❯ ansible-playbook -i k3s_hosts apps。yml。。。PLAY RECAP *****************************************************control : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
完成之後,透過 kubectl 命令檢視部署的 pod
❯ kubectl ——kubeconfig k3s。yaml get po -n whoamiNAME READY STATUS RESTARTS AGEwhoami-5b844ffb57-mffgf 1/1 Running 0 79s❯ kubectl ——kubeconfig k3s。yaml get ingressroute -n whoamiNAME AGEwhoami 2m12s
嘗試訪問 whoami 應用
❯ http http://192。168。123。10/HTTP/1。1 200 OKContent-Length: 413Content-Type: text/plain; charset=utf-8Date: Thu, 13 Oct 2022 08:58:06 GMTHostname: whoami-5b844ffb57-mffgfIP: 127。0。0。1IP: ::1IP: 10。42。2。3IP: fe80::b83a:19ff:febe:7a7fRemoteAddr: 10。42。0。5:60580GET / HTTP/1。1Host: 192。168。123。10User-Agent: HTTPie/3。2。1Accept: */*Accept-Encoding: gzip, deflateX-Forwarded-For: 192。168。123。1X-Forwarded-Host: 192。168。123。10X-Forwarded-Port: 80X-Forwarded-Proto: httpX-Forwarded-Server: traefik-rjbr9X-Real-Ip: 192。168。123。1
銷燬叢集
透過以上方式建立的 K3S 叢集,我們可以很方便的透過 Terraform 銷燬並重新建立。當完成了相關的應用測試之後,我們可以透過以下命令銷燬叢集
❯ rm -f k3s。yaml❯ cd 。。/terraform/❯ terraform destroy ——auto-approve。。。Destroy complete! Resources: 8 destroyed。
我就將會刪除所建立的所有相關資源,恢復乾淨的本地環境。
當需要叢集的時候,只需要執行上面的步驟就可以建立一個新的 K3S 叢集。
總結
這裡演示了一個 IaC 場景,透過程式碼化基礎設施資源,我們可以很容易地透過 Terraform,Ansible 等工具管理並維護相應的基礎設施資源。
這裡我們演示在本地虛擬化環境建立虛擬機器並部署k3S叢集,那透過 Terraform 的其他 Providers (例如 AWS, GCP等共有云),我們可以程式碼化管理我們的公有云基礎設施環境,並可以將相應的流程加入 CI/CD 中,可快速建立需要的環境做測試。
IaC 是現代化基礎設施運維的方向,結合相關工具,我們可以輕鬆實現基礎設施自動化運維。
同時釋出在 Mengz’s Blog