{"id":48849,"date":"2023-03-30T23:40:59","date_gmt":"2023-11-06T15:33:36","guid":{"rendered":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/"},"modified":"2024-04-29T21:14:31","modified_gmt":"2024-04-29T13:14:31","slug":"%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82","status":"publish","type":"post","link":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/","title":{"rendered":"\u4f7f\u7528Terraform + Kubespray\u5728KVM\u4e0a\u6784\u5efaKubernetes\u96c6\u7fa4"},"content":{"rendered":"<h2>\u592a\u957f\u4e0d\u8bfb b\u00f9 d\u00fa)<\/h2>\n<p>\u5728\u5b9a\u4e49\u4e86\u7ec4\u6210\u4e4b\u540e\uff0c\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u547d\u4ee4\u521b\u5efa Kubernetes \u96c6\u7fa4\uff1a<\/p>\n<pre class=\"post-pre\"><code>$ terraform init\r\n$ terraform apply -auto-approve\r\n$ docker run --rm -it \\\r\n  --mount type=bind,source=\"$(pwd)\"\/inventory,dst=\/inventory \\\r\n  --mount type=bind,source=\"$(pwd)\"\/generate_inventory.py,dst=\/kubespray\/generate_inventory.py \\\r\n  --mount type=bind,source=\"$(pwd)\"\/terraform.tfstate,dst=\/kubespray\/terraform.tfstate \\\r\n  --mount type=bind,source=\"${HOME}\"\/.ssh\/id_rsa,dst=\/root\/.ssh\/id_rsa \\\r\n  quay.io\/kubespray\/kubespray:v2.23.1 bash\r\n\r\n# Inside a container\r\n$ ansible-playbook -i generate_inventory.py cluster.yml\r\n<\/code><\/pre>\n<p>\u6837\u672c\u4ee3\u7801\uff1a<\/p>\n<p>&nbsp;<\/p>\n<h2>\u7b80\u8981\u6982\u8ff0<\/h2>\n<p>\u4f7f\u7528Terraform + Kubespray\u5728KVM\u4e0a\u6784\u5efaKubernetes\u96c6\u7fa4\u3002\u5927\u81f4\u6b65\u9aa4\u5982\u4e0b\u3002<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u4f7f\u7528 Terraform \u521b\u5efa\u865a\u62df\u673a<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u4ece\u751f\u6210\u7684 terraform.tfstate \u6587\u4ef6\u4e2d\u63d0\u53d6\u5b58\u8d27\u4fe1\u606f<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ol>\u4f7f\u7528\u5b58\u8d27\u4fe1\u606f\u548c Kuberspray \u7684 Ansible playbooks \u521b\u5efa Kubernetes \u96c6\u7fa4<\/ol>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d87c2913a08637a6c0c09\/8-0.png\" alt=\"dynamic_inventory.drawio.png\" \/><\/div>\n<p>\u7f51\u7edc\u914d\u7f6e\u5982\u4e0b\u56fe\u6240\u793a\uff1a<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d87c2913a08637a6c0c09\/10-0.png\" alt=\"network_architecture.drawio.png\" \/><\/div>\n<p>\u5728\u96c6\u7fa4\u4e2d\uff0c\u5c06\u516c\u5171\u7f51\u7edc\uff08eth0\uff09\u4e0e\u7528\u4e8eAnsible SSH\u767b\u5f55\u7684\u7f51\u7edc\uff08eth1\uff09\u8fdb\u884c\u4e86\u5206\u9694\u3002<\/p>\n<h2>\u524d\u63d0\u6761\u4ef6 (Qian ti tiao jian)<\/h2>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">terraform<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">Container runtime (docker, podman, nerdctl, etc.)<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">KVM packages<\/ul>\n<\/li>\n<\/ul>\n<p>qemu-kvm<br \/>\nlibvirt<\/p>\n<p>crdtools<br \/>\nnmcli<br \/>\n(Host OS: Ubuntu 22.04)<\/p>\n<h2>\u6b65\u9aa4<\/h2>\n<h3>\u4e3b\u6301\u4eba\u7684\u9884\u5148\u8bbe\u7f6e<\/h3>\n<h4>\u7f51\u7edc\u8bbe\u7f6e<\/h4>\n<p>\u521b\u5efa\u4e00\u4e2a\u865a\u62df\u6865\u63a5\u53e3br0\uff0c\u5e76\u5c06\u73b0\u6709\u4e3b\u673a\u7684\u7f51\u7edc\u63a5\u53e3\uff08\u5982enp1s0\uff09\u8fde\u63a5\u5230br0\u3002\u901a\u8fc7\u8fd9\u6837\u505a\uff0c\u53ef\u4ee5\u5c06\u540e\u7eed\u521b\u5efa\u7684\u865a\u62df\u673a\u8fde\u63a5\u5230br0\uff0c\u4f7f\u5f97\u53ef\u4ee5\u76f4\u63a5\u4ece\u5c40\u57df\u7f51\u4e2d\u7684\u4efb\u4f55\u4e3b\u673a\u8bbf\u95ee\u865a\u62df\u673a\u3002<\/p>\n<p>\u56fe\u793a\u8bf4\u660e\u5982\u4e0b\uff0c\u5c06\u8bbe\u7f6e\u4ece &#8220;Before&#8221; \u66f4\u6539\u4e3a &#8220;After&#8221;\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d87c2913a08637a6c0c09\/19-0.png\" alt=\"network-diff.drawio.png\" \/><\/div>\n<pre class=\"post-pre\"><code><span class=\"nv\">$ HOST_IP<\/span><span class=\"o\">=<\/span>192.168.8.10\r\n<span class=\"nv\">$ CIDR<\/span><span class=\"o\">=<\/span>24\r\n<span class=\"nv\">$ GATEWAY<\/span><span class=\"o\">=<\/span>192.168.8.1\r\n<span class=\"nv\">$ DNS<\/span><span class=\"o\">=<\/span>192.168.8.1\r\n<span class=\"nv\">$ NWIF<\/span><span class=\"o\">=<\/span>enp1s0\r\n\r\n<span class=\"c\"># br0 \u3092\u4f5c\u6210<\/span>\r\n<span class=\"nv\">$ <\/span>nmcli connection add <span class=\"nb\">type <\/span>bridge ifname br0\r\n<span class=\"nv\">$ <\/span>nmcli connection show\r\nNAME                UUID                                  TYPE       DEVICE\r\nbridge-br0          55bef68c-1232-46c3-adac-e40964c24d4d  bridge     br0\r\n...\r\n\r\n<span class=\"c\"># \u65e2\u5b58\u306e enp1s0 \u3068\u540c\u3058\u8a2d\u5b9a\u3092 br0 \u306b\u4e0e\u3048\u308b<\/span>\r\n<span class=\"nv\">$ <\/span>nmcli connection modify bridge-br0 <span class=\"se\">\\<\/span>\r\nipv4.method manual <span class=\"se\">\\<\/span>\r\nipv4.addresses <span class=\"s2\">\"<\/span><span class=\"nv\">$HOST_IP<\/span><span class=\"s2\">\/<\/span><span class=\"nv\">$CIDR<\/span><span class=\"s2\">\"<\/span> <span class=\"se\">\\<\/span>\r\nipv4.gateway <span class=\"s2\">\"<\/span><span class=\"nv\">$GATEWAY<\/span><span class=\"s2\">\"<\/span> <span class=\"se\">\\<\/span>\r\nipv4.dns <span class=\"nv\">$DNS<\/span>\r\n\r\n<span class=\"c\"># enp1s0 \u3092 br0 \u306b\u63a5\u7d9a<\/span>\r\n<span class=\"nv\">$ <\/span>nmcli connection add <span class=\"nb\">type <\/span>bridge-slave ifname <span class=\"nv\">$NWIF<\/span> master bridge-br0\r\n<span class=\"c\"># \u65e2\u5b58\u306e enp1s0 \u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u30a4\u30f3\u30bf\u30d5\u30a7\u30fc\u30b9\u3092\u524a\u9664<\/span>\r\n<span class=\"nv\">$ <\/span>nmcli connection delete <span class=\"nv\">$NWIF<\/span>\r\n\r\n<span class=\"c\"># br0 \u306e\u8a2d\u5b9a\u3092\u53cd\u6620<\/span>\r\n<span class=\"nv\">$ <\/span>nmcli connection up bridge-br0\r\n<\/code><\/pre>\n<h4>\u68c0\u67e5libvirt\u7684\u9ed8\u8ba4\u5b58\u50a8\u6c60\u3002<\/h4>\n<p>\u9996\u5148\uff0c\u9700\u8981\u786e\u8ba4\u662f\u5426\u5b58\u5728\u9ed8\u8ba4\u5b58\u50a8\u6c60\uff0clibvirt\u4f7f\u7528\u5404\u79cd\u8d44\u6e90\uff0c\u8fd9\u4e9b\u8d44\u6e90\u5728\u79f0\u4e3a&#8221;default pool&#8221;\u7684\u76ee\u5f55\/var\/lib\/libvirt\/images\u5185\u8fdb\u884c\u7ba1\u7406\u3002<\/p>\n<pre class=\"post-pre\"><code>$ virsh pool-list --all\r\n Name      State    Autostart\r\n-------------------------------\r\n default   active   yes\r\n<\/code><\/pre>\n<p>\u5982\u679c\u6ca1\u6709\u9ed8\u8ba4\u6c60\u7684\u8bdd\uff0c\u5728\u8fd9\u91cc\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u547d\u4ee4\u521b\u5efa\u4e00\u4e2a\uff1a<\/p>\n<pre class=\"post-pre\"><code>$ mkdir \/var\/lib\/libvirt\/images\r\n$ chmod 755 \/var\/lib\/libvirt\/images\r\n\r\n$ virsh pool-define \/dev\/stdin &lt;&lt;EOF\r\n&lt;pool type='dir'&gt;\r\n  &lt;name&gt;default&lt;\/name&gt;\r\n  &lt;target&gt;\r\n    &lt;path&gt;\/var\/lib\/libvirt\/images&lt;\/path&gt;\r\n  &lt;\/target&gt;\r\n&lt;\/pool&gt;\r\nEOF\r\n\r\n$ virsh pool-start default\r\n$ virsh pool-autostart default\r\n$ virsh pool-list --all\r\n<\/code><\/pre>\n<h4>\u83b7\u53d6 Linux \u955c\u50cf<\/h4>\n<p>\u5728\u672c\u6587\u4e2d\uff0c\u6211\u4eec\u5c06\u4f7f\u7528Rocky Linux\u4f5c\u4e3aVM\u7684\u64cd\u4f5c\u7cfb\u7edf\uff0c\u53d6\u4ee3\u539f\u5148\u7684CentOS\u3002\u6211\u4eec\u5c06\u4ecedownload.rockylinux.org\u7f51\u7ad9\u4e0b\u8f7d\u6620\u50cf\u6587\u4ef6\uff0c\u5e76\u5c06\u5176\u4fdd\u5b58\u5230libvirt\u7684\u9ed8\u8ba4\u5b58\u50a8\u6c60\/var\/lib\/libvirt\/images\/\u4e2d\u3002<\/p>\n<pre class=\"post-pre\"><code>$ sudo curl -L -o \/var\/lib\/libvirt\/images\/Rocky-9-GenericCloud.latest.x86_64.qcow2 https:\/\/download.rockylinux.org\/pub\/rocky\/9.2\/images\/x86_64\/Rocky-9-GenericCloud.latest.x86_64.qcow2\r\n<\/code><\/pre>\n<h3>\u4f7f\u7528 Terraform \u8fdb\u884c\u865a\u62df\u673a\u7684\u914d\u7f6e<\/h3>\n<h4>\u4e91\u521d\u59cb\u5316\u914d\u7f6e<\/h4>\n<p>cloud-init\u662f\u4e00\u79cd\u7528\u4e8e\u81ea\u52a8\u5316\u865a\u62df\u673a\u7684\u521d\u59cb\u8bbe\u7f6e\u7684\u673a\u5236\uff0c\u5728\u8bb8\u591aLinux\u53d1\u884c\u7248\u4e2d\u88ab\u91c7\u7528\u3002\u53ef\u4ee5\u901a\u8fc7\u51c6\u5907\u4ee5\u4e0b\u4e24\u4e2a\u914d\u7f6e\u6587\u4ef6\u6765\u63d0\u4f9b\u8bbe\u7f6e\u3002<\/p>\n<p>cloud_init.cfg: \u30e6\u30fc\u30b6\u8a2d\u5b9a\u3092\u8a18\u8ff0<\/p>\n<p>network_config.cfg: \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u8a2d\u5b9a\u3092\u8a18\u8ff0<\/p>\n<pre class=\"post-pre\"><code><span class=\"c1\">#cloud-config<\/span>\r\n<span class=\"na\">users<\/span><span class=\"pi\">:<\/span>\r\n  <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">root<\/span>\r\n    <span class=\"na\">ssh-authorized-keys<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"pi\">-<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">&lt;YOUR_SSH_KEY&gt;\"<\/span> <span class=\"c1\"># \u81ea\u5206\u306e SSH \u516c\u958b\u9375\u3092\u66f8\u304f<\/span>\r\n\r\n<span class=\"na\">runcmd<\/span><span class=\"pi\">:<\/span>\r\n  <span class=\"pi\">-<\/span> <span class=\"s\">dnf install -y python3<\/span>\r\n  <span class=\"pi\">-<\/span> <span class=\"s\">dnf install -y libselinux-python<\/span>\r\n<\/code><\/pre>\n<div>\u5f53\u6267\u884c kubespray \u65f6\uff0c\u9700\u8981\u5b89\u88c5python3\u548clibselinux-python\u3002<\/div>\n<p>\u7f51\u7edc\u8bbe\u7f6e\u7531 network_config.cfg \u63d0\u4f9b\u3002<\/p>\n<p>\u7136\u800c\uff0c\u5982\u679c\u6bcf\u4e2a\u865a\u62df\u673a\u6709\u4e0d\u540c\u7684\u503c\uff08\u4f8b\u5982\u5206\u914d\u9759\u6001 IP \u5730\u5740\uff09\uff0c\u53ef\u4ee5\u521b\u5efa\u4e00\u4e2a\u5305\u542b\u53c2\u6570\u90e8\u5206\u7c7b\u4f3c\u4e8e ${foo} \u7684\u5360\u4f4d\u7b26\u7684\u6a21\u677f\uff0c\u5982\u4e0b\u6240\u793a\u3002\u4f7f\u7528 Terraform \u7684\u6a21\u677f\u529f\u80fd\uff0c\u7a0d\u540e\u53ef\u4ee5\u5c06\u503c\u5206\u914d\u7ed9\u5b83\uff0c\u5e76\u751f\u6210\u6bcf\u4e2a\u865a\u62df\u673a\u7684 network_config.cfg\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"na\">version<\/span><span class=\"pi\">:<\/span> <span class=\"m\">2<\/span>\r\n<span class=\"na\">ethernets<\/span><span class=\"pi\">:<\/span>\r\n  <span class=\"na\">eth0<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">dhcp4<\/span><span class=\"pi\">:<\/span> <span class=\"s\">no<\/span>\r\n    <span class=\"na\">addresses<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">[<\/span><span class=\"nv\">$<\/span><span class=\"pi\">{<\/span><span class=\"nv\">ip<\/span><span class=\"pi\">}]<\/span>\r\n    <span class=\"na\">gateway4<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${gateway}<\/span>\r\n    <span class=\"na\">nameservers<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">addresses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${nameservers}<\/span>\r\n<\/code><\/pre>\n<h4>\u51c6\u5907 Terraform \u7684 libvirt \u63d0\u4f9b\u7a0b\u5e8f<\/h4>\n<p>\u4f7f\u7528Terraform libvirt provider (dmacvicar\/libvirt)\uff0c\u53ef\u4ee5\u901a\u8fc7Terraform\u63a7\u5236libvirt\u3002<\/p>\n<p>\u7531\u4e8elibvirt\u9ed8\u8ba4\u9650\u5236\u5916\u90e8\u5e94\u7528\u7a0b\u5e8f\u5bf9libvirt\u8d44\u6e90\u7684\u8bbf\u95ee\uff0c\u56e0\u6b64\u4e3a\u4e86\u7ed9libvirt\u63d0\u4f9b\u8005\u6388\u4e88\u8bbf\u95ee\u6743\u9650\uff0c\u9700\u8981\u7f16\u8f91\/etc\/apparmor.d\/libvirt\/TEMPLATE.qemu\u6587\u4ef6\u5982\u4e0b\u3002<\/p>\n<pre class=\"post-pre\"><code># This profile is for the domain whose UUID matches this file.\r\n#\r\n\r\n#include &lt;tunables\/global&gt;\r\n\r\nprofile LIBVIRT_TEMPLATE flags=(attach_disconnected) {\r\n  #include &lt;abstractions\/libvirt-qemu&gt;\r\n   \/var\/lib\/libvirt\/images\/** rwk,\r\n   \/tmp\/** rwk,\r\n}\r\n<\/code><\/pre>\n<p>\u91cd\u65b0\u542f\u52a8libvirt\u3002<\/p>\n<pre class=\"post-pre\"><code>$ sudo systemctl restart libvirtd\r\n<\/code><\/pre>\n<h3>\u51c6\u5907Terraform\u6587\u4ef6<\/h3>\n<div>\u672c\u8282\u5c06\u89e3\u91ca\u5982\u4f55\u5b9e\u65bd\u7528\u4e8e\u6784\u5efaKubespray\u7684VM\u7684Terraform\u4ee3\u7801\u3002\u8fd9\u4e9b\u4ee3\u7801\u88ab\u6a21\u5757\u5316\u4e86\uff0c\u6240\u4ee5\u5982\u679c\u4f60\u4e0d\u77e5\u9053\u5982\u4f55\u5b9e\u65bd\uff0c\u4f46\u662f\u60f3\u8981\u5bfc\u5165\u5e76\u4f7f\u7528\u5b83\u4eec\uff0c\u53ef\u4ee5\u53c2\u8003\u672c\u6587\u4e2d\u5173\u4e8e\u5c06\u672c\u6587\u7684Terraform\u4ee3\u7801\u4f5c\u4e3a\u6a21\u5757\u4f7f\u7528\u7684\u6280\u5de7\u3002<\/div>\n<p>\u6587\u4ef6\u7531\u4ee5\u4e0b\u56db\u90e8\u5206\u7ec4\u6210\uff1a<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">provider.tf<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">main.tf<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">variables.tf<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">output.tf<\/ul>\n<h4>provider.tf (\u63d0\u4f9b\u8005.tf)<\/h4>\n<p>\u58f0\u660e\u4f7f\u7528Terraform Libvirt Provider\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">terraform<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">required_providers<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nx\">libvirt<\/span> <span class=\"p\">=<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"nx\">source<\/span>  <span class=\"p\">=<\/span> <span class=\"s2\">\"dmacvicar\/libvirt\"<\/span>\r\n      <span class=\"nx\">version<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"0.7.1\"<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"k\">provider<\/span> <span class=\"s2\">\"libvirt\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">uri<\/span> <span class=\"p\">=<\/span> <span class=\"kd\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">libvirt_uri<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<h4>\u4e3b\u8981.tf<\/h4>\n<p>\u4e3b\u8981\u63cf\u8ff0\u4e0e\u521b\u5efa\u865a\u62df\u673a\u76f8\u5173\u7684\u5904\u7406\u8fc7\u7a0b\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nx\">locals<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">cluster_cidr_splitted<\/span>      <span class=\"p\">=<\/span> <span class=\"nx\">split<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"\/\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">cidr<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"nx\">cluster_cidr_subnet<\/span>        <span class=\"p\">=<\/span> <span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">cluster_cidr_splitted<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\r\n  <span class=\"nx\">cluster_cidr_prefix<\/span>        <span class=\"p\">=<\/span> <span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">cluster_cidr_splitted<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span>\r\n  <span class=\"nx\">cluster_nameservers_string<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"[<\/span><span class=\"se\">\\\"<\/span><span class=\"s2\">${join(\"<\/span><span class=\"p\">\\<\/span><span class=\"s2\">\", <\/span><span class=\"se\">\\\"<\/span><span class=\"s2\">\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">nameservers<\/span><span class=\"p\">)}<\/span><span class=\"err\">\\<\/span><span class=\"s2\">\"]\"<\/span>\r\n\r\n  <span class=\"c1\"># Auto-calculate mac address from IP <\/span>\r\n  <span class=\"nx\">cluster_ips_parts<\/span> <span class=\"err\">=<\/span> <span class=\"p\">[<\/span><span class=\"nx\">for<\/span> <span class=\"nx\">vm<\/span> <span class=\"nx\">in<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span> <span class=\"err\">:<\/span> <span class=\"nx\">split<\/span><span class=\"p\">(<\/span><span class=\"s2\">\".\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">vm<\/span><span class=\"p\">.<\/span><span class=\"nx\">public_ip<\/span><span class=\"p\">)]<\/span>\r\n  <span class=\"nx\">cluster_mac_addrs<\/span> <span class=\"err\">=<\/span> <span class=\"p\">[<\/span>\r\n    <span class=\"nx\">for<\/span> <span class=\"nx\">ip_parts<\/span> <span class=\"nx\">in<\/span> <span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">cluster_ips_parts<\/span> <span class=\"err\">:<\/span> <span class=\"nx\">format<\/span><span class=\"p\">(<\/span>\r\n      <span class=\"s2\">\"52:54:00:%02X:%02X:%02X\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nx\">tonumber<\/span><span class=\"p\">(<\/span><span class=\"nx\">ip_parts<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]),<\/span>\r\n      <span class=\"nx\">tonumber<\/span><span class=\"p\">(<\/span><span class=\"nx\">ip_parts<\/span><span class=\"p\">[<\/span><span class=\"mi\">2<\/span><span class=\"p\">]),<\/span>\r\n      <span class=\"nx\">tonumber<\/span><span class=\"p\">(<\/span><span class=\"nx\">ip_parts<\/span><span class=\"p\">[<\/span><span class=\"mi\">3<\/span><span class=\"p\">])<\/span>\r\n    <span class=\"p\">)<\/span>\r\n  <span class=\"p\">]<\/span>\r\n  <span class=\"nx\">private_ips_parts<\/span> <span class=\"err\">=<\/span> <span class=\"p\">[<\/span><span class=\"nx\">for<\/span> <span class=\"nx\">vm<\/span> <span class=\"nx\">in<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span> <span class=\"err\">:<\/span> <span class=\"nx\">split<\/span><span class=\"p\">(<\/span><span class=\"s2\">\".\"<\/span><span class=\"p\">,<\/span> <span class=\"nx\">vm<\/span><span class=\"p\">.<\/span><span class=\"nx\">private_ip<\/span><span class=\"p\">)]<\/span>\r\n  <span class=\"nx\">private_mac_addrs<\/span> <span class=\"err\">=<\/span> <span class=\"p\">[<\/span>\r\n    <span class=\"nx\">for<\/span> <span class=\"nx\">ip_parts<\/span> <span class=\"nx\">in<\/span> <span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">private_ips_parts<\/span> <span class=\"err\">:<\/span> <span class=\"nx\">format<\/span><span class=\"p\">(<\/span>\r\n      <span class=\"s2\">\"52:54:00:%02X:%02X:%02X\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"nx\">tonumber<\/span><span class=\"p\">(<\/span><span class=\"nx\">ip_parts<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]),<\/span>\r\n      <span class=\"nx\">tonumber<\/span><span class=\"p\">(<\/span><span class=\"nx\">ip_parts<\/span><span class=\"p\">[<\/span><span class=\"mi\">2<\/span><span class=\"p\">]),<\/span>\r\n      <span class=\"nx\">tonumber<\/span><span class=\"p\">(<\/span><span class=\"nx\">ip_parts<\/span><span class=\"p\">[<\/span><span class=\"mi\">3<\/span><span class=\"p\">])<\/span>\r\n    <span class=\"p\">)<\/span>\r\n  <span class=\"p\">]<\/span>\r\n<span class=\"err\">}<\/span>\r\n\r\n<span class=\"nx\">data<\/span> <span class=\"s2\">\"template_file\"<\/span> <span class=\"s2\">\"user_data\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">count<\/span>    <span class=\"p\">=<\/span> <span class=\"nx\">length<\/span><span class=\"p\">(<\/span><span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"nx\">template<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">file<\/span><span class=\"p\">(<\/span><span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">cloudinit_file<\/span><span class=\"p\">)<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">data<\/span> <span class=\"s2\">\"template_file\"<\/span> <span class=\"s2\">\"network_config\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">count<\/span>    <span class=\"p\">=<\/span> <span class=\"nx\">length<\/span><span class=\"p\">(<\/span><span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"nx\">template<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">file<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"${path.module}\/network_config.cfg\"<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"nx\">vars<\/span> <span class=\"p\">=<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nx\">ip<\/span>          <span class=\"p\">=<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">public_ip<\/span>\r\n    <span class=\"nx\">cidr_prefix<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">cluster_cidr_prefix<\/span>\r\n    <span class=\"nx\">gateway<\/span>     <span class=\"p\">=<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">gateway<\/span>\r\n    <span class=\"nx\">nameservers<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">cluster_nameservers_string<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">resource<\/span> <span class=\"s2\">\"libvirt_cloudinit_disk\"<\/span> <span class=\"s2\">\"commoninit\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">count<\/span>          <span class=\"p\">=<\/span> <span class=\"nx\">length<\/span><span class=\"p\">(<\/span><span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"nx\">name<\/span>           <span class=\"p\">=<\/span> <span class=\"s2\">\"commoninit_${var.vms[count.index].name}.iso\"<\/span>\r\n  <span class=\"nx\">user_data<\/span>      <span class=\"p\">=<\/span> <span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">template_file<\/span><span class=\"p\">.<\/span><span class=\"nx\">user_data<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">rendered<\/span>\r\n  <span class=\"nx\">network_config<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">template_file<\/span><span class=\"p\">.<\/span><span class=\"nx\">network_config<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">rendered<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">locals<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">volume_list<\/span>      <span class=\"p\">=<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">for<\/span> <span class=\"nx\">vm<\/span> <span class=\"nx\">in<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span> <span class=\"err\">:<\/span> <span class=\"s2\">\"${vm.name}\"<\/span> <span class=\"p\">=<\/span><span class=\"err\">&gt;<\/span> <span class=\"nx\">flatten<\/span><span class=\"p\">([<\/span><span class=\"nx\">for<\/span> <span class=\"nx\">volume<\/span> <span class=\"nx\">in<\/span> <span class=\"nx\">vm<\/span><span class=\"p\">.<\/span><span class=\"nx\">volumes<\/span> <span class=\"err\">:<\/span> <span class=\"nx\">volume<\/span><span class=\"p\">])<\/span> <span class=\"p\">}<\/span>\r\n  <span class=\"nx\">volume_name_list<\/span> <span class=\"p\">=<\/span> <span class=\"p\">[<\/span><span class=\"nx\">for<\/span> <span class=\"nx\">vm<\/span><span class=\"p\">,<\/span> <span class=\"nx\">volumes<\/span> <span class=\"nx\">in<\/span> <span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">volume_list<\/span> <span class=\"err\">:<\/span> <span class=\"p\">[<\/span><span class=\"nx\">for<\/span> <span class=\"nx\">volume<\/span> <span class=\"nx\">in<\/span> <span class=\"nx\">volumes<\/span> <span class=\"err\">:<\/span> <span class=\"p\">{<\/span> <span class=\"s2\">\"name\"<\/span> <span class=\"err\">:<\/span> <span class=\"s2\">\"${vm}_${volume.name}\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"disk\"<\/span> <span class=\"err\">:<\/span> <span class=\"nx\">volume<\/span><span class=\"p\">.<\/span><span class=\"nx\">disk<\/span> <span class=\"p\">}]]<\/span>\r\n  <span class=\"nx\">volumes<\/span>          <span class=\"p\">=<\/span> <span class=\"nx\">flatten<\/span><span class=\"p\">(<\/span><span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">volume_name_list<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"nx\">volumes_indexed<\/span>  <span class=\"p\">=<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">for<\/span> <span class=\"nx\">index<\/span><span class=\"p\">,<\/span> <span class=\"nx\">volume<\/span> <span class=\"nx\">in<\/span> <span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">volumes<\/span> <span class=\"err\">:<\/span> <span class=\"nx\">volume<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span> <span class=\"p\">=<\/span><span class=\"err\">&gt;<\/span> <span class=\"nx\">index<\/span> <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">resource<\/span> <span class=\"s2\">\"libvirt_domain\"<\/span> <span class=\"s2\">\"vm\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">count<\/span>  <span class=\"p\">=<\/span> <span class=\"nx\">length<\/span><span class=\"p\">(<\/span><span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"nx\">name<\/span>   <span class=\"p\">=<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">name<\/span>\r\n  <span class=\"nx\">vcpu<\/span>   <span class=\"p\">=<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">vcpu<\/span>\r\n  <span class=\"nx\">memory<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">memory<\/span>\r\n\r\n  <span class=\"nx\">disk<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nx\">volume_id<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">libvirt_volume<\/span><span class=\"p\">.<\/span><span class=\"nx\">system<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">id<\/span>\r\n  <span class=\"p\">}<\/span>\r\n\r\n  <span class=\"nx\">cloudinit<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">libvirt_cloudinit_disk<\/span><span class=\"p\">.<\/span><span class=\"nx\">commoninit<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">id<\/span>\r\n  <span class=\"nx\">autostart<\/span> <span class=\"p\">=<\/span> <span class=\"kc\">true<\/span>\r\n\r\n  <span class=\"c1\"># Public network<\/span>\r\n  <span class=\"nx\">network_interface<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nx\">bridge<\/span>    <span class=\"p\">=<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">bridge<\/span>\r\n    <span class=\"nx\">addresses<\/span> <span class=\"p\">=<\/span> <span class=\"p\">[<\/span><span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">public_ip<\/span><span class=\"p\">]<\/span>\r\n    <span class=\"nx\">mac<\/span>       <span class=\"p\">=<\/span> <span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">cluster_mac_addrs<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">]<\/span>\r\n  <span class=\"p\">}<\/span>\r\n\r\n  <span class=\"c1\"># Private network<\/span>\r\n  <span class=\"nx\">network_interface<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nx\">network_name<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"default\"<\/span>\r\n    <span class=\"nx\">addresses<\/span>    <span class=\"p\">=<\/span> <span class=\"p\">[<\/span><span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">private_ip<\/span><span class=\"p\">]<\/span>\r\n    <span class=\"nx\">mac<\/span>          <span class=\"p\">=<\/span> <span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">private_mac_addrs<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">]<\/span>\r\n  <span class=\"p\">}<\/span>\r\n\r\n  <span class=\"nx\">qemu_agent<\/span> <span class=\"p\">=<\/span> <span class=\"kc\">true<\/span>\r\n\r\n  <span class=\"nx\">cpu<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nx\">mode<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"host-passthrough\"<\/span>\r\n  <span class=\"p\">}<\/span>\r\n\r\n  <span class=\"nx\">graphics<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nx\">type<\/span>        <span class=\"p\">=<\/span> <span class=\"s2\">\"vnc\"<\/span>\r\n    <span class=\"nx\">listen_type<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"address\"<\/span>\r\n  <span class=\"p\">}<\/span>\r\n\r\n  <span class=\"c1\"># Makes the tty0 available via `virsh console`<\/span>\r\n  <span class=\"nx\">console<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nx\">type<\/span>        <span class=\"p\">=<\/span> <span class=\"s2\">\"pty\"<\/span>\r\n    <span class=\"nx\">target_port<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"0\"<\/span>\r\n    <span class=\"nx\">target_type<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"serial\"<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">resource<\/span> <span class=\"s2\">\"libvirt_volume\"<\/span> <span class=\"s2\">\"system\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">count<\/span>          <span class=\"p\">=<\/span> <span class=\"nx\">length<\/span><span class=\"p\">(<\/span><span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"nx\">name<\/span>           <span class=\"p\">=<\/span> <span class=\"s2\">\"${var.vms[count.index].name}_system.qcow2\"<\/span>\r\n  <span class=\"nx\">pool<\/span>           <span class=\"p\">=<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">pool<\/span>\r\n  <span class=\"nx\">format<\/span>         <span class=\"p\">=<\/span> <span class=\"s2\">\"qcow2\"<\/span>\r\n  <span class=\"nx\">base_volume_id<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vm_base_image_uri<\/span>\r\n  <span class=\"nx\">size<\/span>           <span class=\"p\">=<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span><span class=\"p\">[<\/span><span class=\"nx\">count<\/span><span class=\"p\">.<\/span><span class=\"nx\">index<\/span><span class=\"p\">].<\/span><span class=\"nx\">disk<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<h4>variables.tf\u7684\u610f\u601d\u662ftf\u662f\u6307Terraform\uff0cvariables\u662f\u6307\u53d8\u91cf\uff0c.tf\u662f\u6307Terraform\u7684\u6587\u4ef6\u6269\u5c55\u540d\u3002<\/h4>\n<p>\u58f0\u660e\u53d8\u91cf\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nx\">variable<\/span> <span class=\"s2\">\"libvirt_uri\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">type<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">string<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">variable<\/span> <span class=\"s2\">\"vm_base_image_uri\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">type<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">string<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">variable<\/span> <span class=\"s2\">\"bridge\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">type<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">string<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">variable<\/span> <span class=\"s2\">\"gateway\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">type<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">string<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">variable<\/span> <span class=\"s2\">\"cidr\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">type<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">string<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">variable<\/span> <span class=\"s2\">\"nameservers\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">type<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">list<\/span><span class=\"p\">(<\/span><span class=\"nx\">string<\/span><span class=\"p\">)<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">variable<\/span> <span class=\"s2\">\"pool\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">type<\/span>    <span class=\"p\">=<\/span> <span class=\"nx\">string<\/span>\r\n  <span class=\"nx\">default<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"default\"<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">variable<\/span> <span class=\"s2\">\"vms\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">type<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">list<\/span><span class=\"p\">(<\/span>\r\n    <span class=\"nx\">object<\/span><span class=\"p\">({<\/span>\r\n      <span class=\"nx\">name<\/span>           <span class=\"p\">=<\/span> <span class=\"nx\">string<\/span>\r\n      <span class=\"nx\">vcpu<\/span>           <span class=\"p\">=<\/span> <span class=\"nx\">number<\/span>\r\n      <span class=\"nx\">memory<\/span>         <span class=\"p\">=<\/span> <span class=\"nx\">number<\/span>\r\n      <span class=\"nx\">disk<\/span>           <span class=\"p\">=<\/span> <span class=\"nx\">number<\/span>\r\n      <span class=\"nx\">public_ip<\/span>      <span class=\"p\">=<\/span> <span class=\"nx\">string<\/span>\r\n      <span class=\"nx\">private_ip<\/span>     <span class=\"p\">=<\/span> <span class=\"nx\">string<\/span>\r\n      <span class=\"nx\">cloudinit_file<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">string<\/span>\r\n\r\n      <span class=\"nx\">kube_control_plane<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">bool<\/span>\r\n      <span class=\"nx\">kube_node<\/span>          <span class=\"p\">=<\/span> <span class=\"nx\">bool<\/span>\r\n      <span class=\"nx\">etcd<\/span>               <span class=\"p\">=<\/span> <span class=\"nx\">bool<\/span>\r\n    <span class=\"p\">})<\/span>\r\n  <span class=\"p\">)<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<\/code><\/pre>\n<h4>output.tf \u7684\u6c49\u8bed\u7ffb\u8bd1\u662f\u8f93\u51fa.tf\u3002<\/h4>\n<p>\u5728\u63a5\u4e0b\u6765\u7684\u8fc7\u7a0b\u4e2d\uff0c\u8f93\u51fa\u8981\u4f20\u9012\u7ed9Ansible\u7684\u4e3b\u673a\u4fe1\u606f\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nx\">locals<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">kubespray_hosts_keys<\/span> <span class=\"p\">=<\/span> <span class=\"p\">[<\/span><span class=\"s2\">\"name\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"kube_control_plane\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"kube_node\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"etcd\"<\/span><span class=\"p\">]<\/span>\r\n  <span class=\"nx\">kubespray_hosts<\/span> <span class=\"p\">=<\/span> <span class=\"p\">[<\/span><span class=\"nx\">for<\/span> <span class=\"nx\">vm<\/span> <span class=\"nx\">in<\/span> <span class=\"nx\">var<\/span><span class=\"p\">.<\/span><span class=\"nx\">vms<\/span> <span class=\"err\">:<\/span>\r\n    <span class=\"nx\">merge<\/span><span class=\"p\">(<\/span>\r\n      <span class=\"p\">{<\/span>\r\n        <span class=\"nx\">for<\/span> <span class=\"nx\">key<\/span><span class=\"p\">,<\/span> <span class=\"nx\">value<\/span> <span class=\"nx\">in<\/span> <span class=\"nx\">vm<\/span> <span class=\"err\">:<\/span> <span class=\"nx\">key<\/span> <span class=\"p\">=<\/span><span class=\"err\">&gt;<\/span> <span class=\"nx\">value<\/span> <span class=\"nx\">if<\/span> <span class=\"nx\">contains<\/span><span class=\"p\">(<\/span><span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">kubespray_hosts_keys<\/span><span class=\"p\">,<\/span> <span class=\"nx\">key<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"p\">},<\/span>\r\n      <span class=\"p\">{<\/span>\r\n        <span class=\"nx\">ip<\/span>        <span class=\"p\">=<\/span> <span class=\"nx\">vm<\/span><span class=\"p\">.<\/span><span class=\"nx\">public_ip<\/span>\r\n        <span class=\"nx\">access_ip<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">vm<\/span><span class=\"p\">.<\/span><span class=\"nx\">private_ip<\/span>\r\n    <span class=\"p\">})<\/span>\r\n  <span class=\"p\">]<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">output<\/span> <span class=\"s2\">\"kubespray_hosts\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">value<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">local<\/span><span class=\"p\">.<\/span><span class=\"nx\">kubespray_hosts<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<h3>\u6267\u884c Terraform<\/h3>\n<p>\u6267\u884cTerraform\u5e76\u8fdb\u884c\u865a\u62df\u673a\u914d\u7f6e\u3002<\/p>\n<pre class=\"post-pre\"><code>$ terraform init\r\n$ terraform apply -auto-approve\r\n<\/code><\/pre>\n<p>\u786e\u8ba4\u865a\u62df\u673a\u5df2\u7ecf\u88ab\u521b\u5efa\u5e76\u6b63\u5728\u8fd0\u884c\u3002<\/p>\n<pre class=\"post-pre\"><code>$ virsh list --all\r\n Id   Name           State\r\n------------------------------\r\n 1    k8s-master-1   running\r\n 2    k8s-worker-1   running\r\n 3    k8s-worker-2   running\r\n<\/code><\/pre>\n<p>\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u547d\u4ee4\u786e\u8ba4\u521b\u5efa\u7684\u865a\u62df\u673a\u5df2\u8fde\u63a5\u5230br0\u3002<\/p>\n<pre class=\"post-pre\"><code>$ ip link show master br0\r\nbridge name     bridge id               STP enabled     interfaces\r\n2: enp1s0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq master br0 state UP mode DEFAULT group default qlen 1000\r\n    link\/ether 48:21:0b:57:b2:52 brd ff:ff:ff:ff:ff:ff\r\n5: vnet4: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue master br0 state UNKNOWN mode DEFAULT group default qlen 1000\r\n    link\/ether fe:54:00:00:00:04 brd ff:ff:ff:ff:ff:ff\r\n6: vnet5: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue master br0 state UNKNOWN mode DEFAULT group default qlen 1000\r\n    link\/ether fe:54:00:00:00:02 brd ff:ff:ff:ff:ff:ff\r\n7: vnet6: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue master br0 state UNKNOWN mode DEFAULT group default qlen 1000\r\n    link\/ether fe:54:00:00:00:03 brd ff:ff:ff:ff:ff:ff\r\n8: vnet7: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue master br0 state UNKNOWN mode DEFAULT group default qlen 1000\r\n    link\/ether fe:54:00:00:00:01 brd ff:ff:ff:ff:ff:ff\r\n<\/code><\/pre>\n<h3>\u4f7f\u7528 Kubespray \u6765\u521b\u5efa Kubernetes \u96c6\u7fa4\u3002<\/h3>\n<p>Kubespray\u662f\u4e00\u4e2a\u5f00\u6e90\u9879\u76ee\uff0c\u63d0\u4f9b\u4e86\u81ea\u52a8\u5316\u6784\u5efaKubernetes\u96c6\u7fa4\u7684Ansible playbook\u3002\u6309\u7167kubespray\/docs\/setting-up-your-first-cluster.md at master \u00b7 kubernetes-sigs\/kubespray\u4e2d\u7684\u6b65\u9aa4\u8fdb\u884c\u64cd\u4f5c\u3002<\/p>\n<p>\u9996\u5148\uff0c\u514b\u9686 kubespray \u7684\u4ee3\u7801\u5e93\u3002<\/p>\n<pre class=\"post-pre\"><code>$ git clone git@github.com:kubernetes-sigs\/kubespray.git\r\n$ cd kubespray\r\n<\/code><\/pre>\n<p>\u63a5\u4e0b\u6765\uff0c\u590d\u5236\u73b0\u6709\u7684\u6837\u672c\u5e76\u521b\u5efa\u914d\u7f6e\u6587\u4ef6\u7684\u57fa\u7840\u3002<\/p>\n<pre class=\"post-pre\"><code>$ git checkout release-2.23\r\n$ cp -rfp inventory\/sample inventory\/mycluster\r\n<\/code><\/pre>\n<p>\u5728\u672c\u6587\u4e2d\uff0c\u6211\u4eec\u51b3\u5b9a\u4f7f\u7528crio\u4f5c\u4e3a\u5bb9\u5668\u8fd0\u884c\u65f6\uff08\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u662fcontainerd\uff09\u3002\u5c06group_vars\/k8s_cluster\/k8s_cluster.yml\u4e2d\u7684container_manager\u7684\u503c\u66f4\u6539\u4e3acrio\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"c1\">## Container runtime<\/span>\r\n<span class=\"c1\">## docker for docker, crio for cri-o and containerd for containerd.<\/span>\r\n<span class=\"c1\">## Default: containerd<\/span>\r\n<span class=\"na\">container_manager<\/span><span class=\"pi\">:<\/span> <span class=\"s\">crio<\/span>\r\n<\/code><\/pre>\n<p>\u5982\u679c\u8981\u8bbe\u7f6e\u66f4\u8be6\u7ec6\u7684\u9009\u9879\uff0c\u8bf7\u4fee\u6539 inventory\/mycluster\/group_vars\/ \u76ee\u5f55\u4e0b\u7684\u6587\u4ef6\uff08\u9644\u6ce8\uff1a\u4ee3\u7406\u8bbe\u7f6e\uff09\u3002<\/p>\n<h4>\u521b\u5efa\u5e93\u5b58\u6e05\u5355<\/h4>\n<p>\u6211\u5c06\u4ecb\u7ecd\u4ee5\u4e0b\u4e24\u79cd\u65b9\u6cd5\uff0c\u4f46\u4f60\u53ea\u9700\u8981\u9009\u62e9\u5176\u4e2d\u4e00\u79cd\u5c31\u53ef\u4ee5\u4e86\u3002<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\u4f7f\u7528\u52a8\u6001\u5e93\u5b58\u7684\u65b9\u6cd5\u3002<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ol>\u624b\u52a8\u7f16\u8f91hosts.yaml\u6587\u4ef6\u7684\u65b9\u6cd5\u3002<\/ol>\n<h5>\u4f7f\u7528\u52a8\u6001\u5e93\u5b58\u65b9\u6cd5<\/h5>\n<p>\u5728\u6267\u884cterraform\u540e\uff0c\u4ece\u751f\u6210\u7684terraform.tfstate\u6587\u4ef6\u4e2d\u52a8\u6001\u5730\u63d0\u53d6\u6e05\u5355\u4fe1\u606f\u3002<\/p>\n<p>\u53ea\u9700\u51c6\u5907\u4e00\u4e2a\u4ec5\u8fdb\u884c\u8f93\u51fa\u7684\u811a\u672c\uff08\u793a\u4f8b\u5b9e\u73b0\uff1a.\/generate_inventory.py\uff09\uff0c\u8be5\u811a\u672c\u5c06\u8f93\u51fa\u4ee5 JSON \u63cf\u8ff0\u7684 inventory \u4fe1\u606f\u3002\u4ee5\u4e0b\u662f\u4e00\u4e2a\u8bfb\u53d6 terraform.state \u7684 .outputs \u5e76\u521b\u5efa inventory \u7684\u811a\u672c\u5b9e\u73b0\u793a\u4f8b\uff1a<\/p>\n<pre class=\"post-pre\"><code><span class=\"c1\">#!\/usr\/bin\/env python3\r\n<\/span>\r\n<span class=\"kn\">import<\/span> <span class=\"n\">json<\/span>\r\n<span class=\"kn\">import<\/span> <span class=\"n\">re<\/span>\r\n\r\n\r\n<span class=\"k\">def<\/span> <span class=\"nf\">main<\/span><span class=\"p\">():<\/span>\r\n    <span class=\"n\">output<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">get_outputs<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"n\">hosts<\/span> <span class=\"o\">=<\/span> <span class=\"n\">output<\/span><span class=\"p\">[<\/span><span class=\"sh\">'<\/span><span class=\"s\">kubespray_hosts<\/span><span class=\"sh\">'<\/span><span class=\"p\">][<\/span><span class=\"sh\">'<\/span><span class=\"s\">value<\/span><span class=\"sh\">'<\/span><span class=\"p\">]<\/span>\r\n    <span class=\"n\">libvirt_uri<\/span> <span class=\"o\">=<\/span> <span class=\"n\">output<\/span><span class=\"p\">[<\/span><span class=\"sh\">'<\/span><span class=\"s\">libvirt_uri<\/span><span class=\"sh\">'<\/span><span class=\"p\">][<\/span><span class=\"sh\">'<\/span><span class=\"s\">value<\/span><span class=\"sh\">'<\/span><span class=\"p\">]<\/span>\r\n\r\n    <span class=\"n\">hostvars<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{}<\/span>\r\n    <span class=\"n\">kube_control_plane<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\r\n    <span class=\"n\">kube_node<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\r\n    <span class=\"n\">etcd<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\r\n\r\n    <span class=\"k\">for<\/span> <span class=\"n\">host<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">hosts<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"n\">name<\/span> <span class=\"o\">=<\/span> <span class=\"n\">host<\/span><span class=\"p\">[<\/span><span class=\"sh\">'<\/span><span class=\"s\">name<\/span><span class=\"sh\">'<\/span><span class=\"p\">]<\/span>\r\n        <span class=\"n\">ip<\/span> <span class=\"o\">=<\/span> <span class=\"n\">host<\/span><span class=\"p\">[<\/span><span class=\"sh\">'<\/span><span class=\"s\">ip<\/span><span class=\"sh\">'<\/span><span class=\"p\">]<\/span>\r\n        <span class=\"n\">access_ip<\/span> <span class=\"o\">=<\/span> <span class=\"n\">host<\/span><span class=\"p\">[<\/span><span class=\"sh\">'<\/span><span class=\"s\">access_ip<\/span><span class=\"sh\">'<\/span><span class=\"p\">]<\/span>\r\n        <span class=\"n\">hostvars<\/span><span class=\"p\">.<\/span><span class=\"nf\">update<\/span><span class=\"p\">({<\/span>\r\n          <span class=\"n\">name<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n              <span class=\"sh\">\"<\/span><span class=\"s\">ansible_host<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">access_ip<\/span><span class=\"p\">,<\/span>\r\n              <span class=\"sh\">\"<\/span><span class=\"s\">ip<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">ip<\/span><span class=\"p\">,<\/span>\r\n          <span class=\"p\">}<\/span>\r\n        <span class=\"p\">})<\/span>\r\n\r\n        <span class=\"n\">regex<\/span> <span class=\"o\">=<\/span> <span class=\"sa\">r<\/span><span class=\"sh\">\"<\/span><span class=\"s\">^qemu(\\+ssh)?:\/\/([^\/]*)\/.*<\/span><span class=\"sh\">\"<\/span>\r\n        <span class=\"n\">res<\/span> <span class=\"o\">=<\/span> <span class=\"n\">re<\/span><span class=\"p\">.<\/span><span class=\"nf\">match<\/span><span class=\"p\">(<\/span><span class=\"n\">regex<\/span><span class=\"p\">,<\/span> <span class=\"n\">libvirt_uri<\/span><span class=\"p\">)<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"n\">res<\/span><span class=\"p\">:<\/span>\r\n          <span class=\"n\">hostname<\/span> <span class=\"o\">=<\/span> <span class=\"n\">res<\/span><span class=\"p\">[<\/span><span class=\"mi\">2<\/span><span class=\"p\">]<\/span>\r\n          <span class=\"k\">if<\/span> <span class=\"n\">hostname<\/span> <span class=\"o\">!=<\/span> <span class=\"sh\">\"\"<\/span><span class=\"p\">:<\/span>\r\n            <span class=\"n\">hostvars<\/span><span class=\"p\">[<\/span><span class=\"n\">name<\/span><span class=\"p\">].<\/span><span class=\"nf\">update<\/span><span class=\"p\">({<\/span>\r\n              <span class=\"sh\">\"<\/span><span class=\"s\">ansible_ssh_common_args<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"sa\">f<\/span><span class=\"sh\">\"<\/span><span class=\"s\">-J <\/span><span class=\"si\">{<\/span><span class=\"n\">hostname<\/span><span class=\"si\">}<\/span><span class=\"sh\">\"<\/span>\r\n          <span class=\"p\">})<\/span>\r\n\r\n        <span class=\"k\">if<\/span> <span class=\"n\">host<\/span><span class=\"p\">[<\/span><span class=\"sh\">\"<\/span><span class=\"s\">kube_control_plane<\/span><span class=\"sh\">\"<\/span><span class=\"p\">]:<\/span>\r\n            <span class=\"n\">kube_control_plane<\/span><span class=\"p\">.<\/span><span class=\"nf\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">name<\/span><span class=\"p\">)<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"n\">host<\/span><span class=\"p\">[<\/span><span class=\"sh\">\"<\/span><span class=\"s\">kube_node<\/span><span class=\"sh\">\"<\/span><span class=\"p\">]:<\/span>\r\n            <span class=\"n\">kube_node<\/span><span class=\"p\">.<\/span><span class=\"nf\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">name<\/span><span class=\"p\">)<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"n\">host<\/span><span class=\"p\">[<\/span><span class=\"sh\">\"<\/span><span class=\"s\">etcd<\/span><span class=\"sh\">\"<\/span><span class=\"p\">]:<\/span>\r\n            <span class=\"n\">etcd<\/span><span class=\"p\">.<\/span><span class=\"nf\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">name<\/span><span class=\"p\">)<\/span>\r\n\r\n    <span class=\"n\">inventory<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"sh\">\"<\/span><span class=\"s\">_meta<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n            <span class=\"sh\">\"<\/span><span class=\"s\">hostvars<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">hostvars<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"p\">},<\/span>\r\n        <span class=\"sh\">\"<\/span><span class=\"s\">kube_control_plane<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">kube_control_plane<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"sh\">\"<\/span><span class=\"s\">kube_node<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">kube_node<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"sh\">\"<\/span><span class=\"s\">etcd<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">etcd<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"sh\">\"<\/span><span class=\"s\">k8s_cluster<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n            <span class=\"sh\">\"<\/span><span class=\"s\">children<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\r\n                <span class=\"sh\">\"<\/span><span class=\"s\">kube_control_plane<\/span><span class=\"sh\">\"<\/span><span class=\"p\">,<\/span>\r\n                <span class=\"sh\">\"<\/span><span class=\"s\">kube_node<\/span><span class=\"sh\">\"<\/span><span class=\"p\">,<\/span>\r\n            <span class=\"p\">]<\/span>\r\n        <span class=\"p\">}<\/span>\r\n    <span class=\"p\">}<\/span>\r\n\r\n\r\n    <span class=\"nf\">print<\/span><span class=\"p\">(<\/span><span class=\"n\">json<\/span><span class=\"p\">.<\/span><span class=\"nf\">dumps<\/span><span class=\"p\">(<\/span><span class=\"n\">inventory<\/span><span class=\"p\">))<\/span>\r\n\r\n\r\n<span class=\"k\">def<\/span> <span class=\"nf\">get_outputs<\/span><span class=\"p\">():<\/span>\r\n    <span class=\"n\">tfstate_path<\/span> <span class=\"o\">=<\/span> <span class=\"sh\">'<\/span><span class=\"s\">.\/terraform.tfstate<\/span><span class=\"sh\">'<\/span>\r\n    <span class=\"k\">with<\/span> <span class=\"nf\">open<\/span><span class=\"p\">(<\/span><span class=\"n\">tfstate_path<\/span><span class=\"p\">)<\/span> <span class=\"k\">as<\/span> <span class=\"n\">f<\/span><span class=\"p\">:<\/span>\r\n        <span class=\"n\">tfstate<\/span> <span class=\"o\">=<\/span> <span class=\"n\">json<\/span><span class=\"p\">.<\/span><span class=\"nf\">load<\/span><span class=\"p\">(<\/span><span class=\"n\">f<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">return<\/span> <span class=\"n\">tfstate<\/span><span class=\"p\">[<\/span><span class=\"sh\">'<\/span><span class=\"s\">outputs<\/span><span class=\"sh\">'<\/span><span class=\"p\">]<\/span>\r\n\r\n\r\n<span class=\"nf\">main<\/span><span class=\"p\">()<\/span>\r\n<\/code><\/pre>\n<p>\u8fd0\u884c\u6b64generate_inventory.py\u811a\u672c\u4f1a\u8f93\u51fa\u4ee5\u4e0bJSON\uff1a<\/p>\n<pre class=\"post-pre\"><code><span class=\"p\">{<\/span>\r\n  <span class=\"nl\">\"_meta\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nl\">\"hostvars\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"nl\">\"storage1\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"nl\">\"ansible_host\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"192.168.122.201\"<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"nl\">\"ip\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"192.168.8.201\"<\/span>\r\n      <span class=\"p\">},<\/span>\r\n      <span class=\"nl\">\"storage2\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"nl\">\"ansible_host\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"192.168.122.202\"<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"nl\">\"ip\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"192.168.8.202\"<\/span>\r\n      <span class=\"p\">},<\/span>\r\n      <span class=\"nl\">\"storage3\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n        <span class=\"nl\">\"ansible_host\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"192.168.122.203\"<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"nl\">\"ip\"<\/span><span class=\"p\">:<\/span> <span class=\"s2\">\"192.168.8.203\"<\/span>\r\n      <span class=\"p\">}<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">},<\/span>\r\n  <span class=\"nl\">\"kube_control_plane\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\r\n    <span class=\"s2\">\"storage1\"<\/span>\r\n  <span class=\"p\">],<\/span>\r\n  <span class=\"nl\">\"kube_node\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\r\n    <span class=\"s2\">\"storage1\"<\/span><span class=\"p\">,<\/span>\r\n    <span class=\"s2\">\"storage2\"<\/span><span class=\"p\">,<\/span>\r\n    <span class=\"s2\">\"storage3\"<\/span>\r\n  <span class=\"p\">],<\/span>\r\n  <span class=\"nl\">\"etcd\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\r\n    <span class=\"s2\">\"storage1\"<\/span>\r\n  <span class=\"p\">],<\/span>\r\n  <span class=\"nl\">\"k8s_cluster\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"nl\">\"children\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\r\n      <span class=\"s2\">\"kube_control_plane\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"s2\">\"kube_node\"<\/span>\r\n    <span class=\"p\">]<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<p>\u6307\u5b9a\u8fd9\u4e2a\u4f5c\u4e3a\u5e93\u5b58\uff0c\u5e76\u521b\u5efaKubernetes\u96c6\u7fa4\uff1a<\/p>\n<pre class=\"post-pre\"><code>$ docker pull quay.io\/kubespray\/kubespray:v2.23.1\r\n$ docker run --rm -it \\\r\n  --mount type=bind,source=\"$(pwd)\"\/inventory,dst=\/inventory \\\r\n  --mount type=bind,source=\"$(pwd)\"\/generate_inventory.py,dst=\/kubespray\/generate_inventory.py \\\r\n  --mount type=bind,source=\"$(pwd)\"\/terraform.tfstate,dst=\/kubespray\/terraform.tfstate \\\r\n  --mount type=bind,source=\"${HOME}\"\/.ssh\/id_rsa,dst=\/root\/.ssh\/id_rsa \\\r\n  quay.io\/kubespray\/kubespray:v2.23.1 bash\r\n\r\n# Inside a container\r\n$ ansible-playbook -i generate_inventory.py cluster.yml\r\n\u2026\r\nPLAY RECAP *****************************************************************************************************************\r\nlocalhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   \r\nk8s-master-1               : ok=765  changed=138  unreachable=0    failed=0    skipped=1263 rescued=0    ignored=8   \r\nk8s-worker-1               : ok=583  changed=104  unreachable=0    failed=0    skipped=795  rescued=0    ignored=2   \r\nk8s-worker-2               : ok=523  changed=82   unreachable=0    failed=0    skipped=763  rescued=0    ignored=1   \r\n\r\nTuesday 01 August 2023  13:16:52 +0000 (0:00:00.041)       0:59:01.983 ********                                                                                      ===============================================================================      \r\n<\/code><\/pre>\n<p>\u5982\u679c\u5728\u5b89\u88c5\u8fc7\u7a0b\u4e2d\u51fa\u73b0\u6545\u969c\u6216\u5176\u4ed6\u539f\u56e0\u60f3\u8981\u91cd\u65b0\u5b89\u88c5\u7684\u8bdd\uff0c\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u65b9\u6cd5\u8fdb\u884c\u91cd\u7f6e\u3002<\/p>\n<pre class=\"post-pre\"><code>$ ansible-playbook -i .\/generate_inventory.py reset.yml\r\n<\/code><\/pre>\n<p>\u8bf7\u53c2\u8003Kubespray\u5b98\u65b9\u4ed3\u5e93\u7684 https:\/\/github.com\/kubernetes-sigs\/kubespray\/blob\/master\/docs\/aws.md#dynamic-inventory \uff0c\u83b7\u53d6\u6709\u5173Kubespray\u52a8\u6001\u6e05\u5355\u7684\u8be6\u7ec6\u4fe1\u606f\u3002<\/p>\n<h5>(\u9009\u98792) \u624b\u52a8\u7f16\u8f91 hosts.yaml<\/h5>\n<p>\u542f\u52a8 kubespray \u5bb9\u5668\u3002<\/p>\n<pre class=\"post-pre\"><code>$ docker pull quay.io\/kubespray\/kubespray:v2.23.1\r\n$ docker run --rm -it \\\r\n  --mount type=bind,source=\"$(pwd)\"\/inventory\/mycluster,dst=\/inventory \\\r\n  --mount type=bind,source=\"${HOME}\"\/.ssh\/id_rsa,dst=\/root\/.ssh\/id_rsa \\\r\n  quay.io\/kubespray\/kubespray:v2.23.1 bash\r\n<\/code><\/pre>\n<p>\u8fdb\u5165\u5bb9\u5668\u540e\uff0c\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\u3002<\/p>\n<pre class=\"post-pre\"><code>$ declare -a IPS=(192.168.8.201 192.168.8.202 192.168.8.203)\r\n$ CONFIG_FILE=\/inventory\/hosts.yaml python3 contrib\/inventory_builder\/inventory.py ${IPS[@]}\r\n<\/code><\/pre>\n<p>\u56e0\u4e3a\u751f\u6210\u4e86\u5b58\u8d27\u6587\u4ef6 \/inventory\/mycluster\/hosts.yaml\uff0c\u56e0\u6b64\u6839\u636e\u9700\u8981\u8fdb\u884c\u4fee\u6b63\u4e3b\u673a\u4fe1\u606f\u3002\u5728\u672c\u6587\u4e2d\uff0c\u6211\u4eec\u4f7f\u7528\u4ee5\u4e0b\u914d\u7f6e\uff1a<\/p>\n<pre class=\"post-pre\"><code><span class=\"na\">all<\/span><span class=\"pi\">:<\/span>\r\n  <span class=\"na\">hosts<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">storage1<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">ansible_host<\/span><span class=\"pi\">:<\/span> <span class=\"s\">192.168.122.201<\/span>\r\n      <span class=\"na\">ip<\/span><span class=\"pi\">:<\/span> <span class=\"s\">192.168.8.201<\/span>\r\n    <span class=\"na\">storage2<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">ansible_host<\/span><span class=\"pi\">:<\/span> <span class=\"s\">192.168.122.202<\/span>\r\n      <span class=\"na\">ip<\/span><span class=\"pi\">:<\/span> <span class=\"s\">192.168.8.202<\/span>\r\n    <span class=\"na\">storage3<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">ansible_host<\/span><span class=\"pi\">:<\/span> <span class=\"s\">192.168.122.203<\/span>\r\n      <span class=\"na\">ip<\/span><span class=\"pi\">:<\/span> <span class=\"s\">192.168.8.203<\/span>\r\n  <span class=\"na\">children<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">kube_control_plane<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">hosts<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">storage1<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">kube_node<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">hosts<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">storage1<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">storage2<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">storage3<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">etcd<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">hosts<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">storage1<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"na\">k8s_cluster<\/span><span class=\"pi\">:<\/span>\r\n      <span class=\"na\">children<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">kube_control_plane<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">kube_node<\/span><span class=\"pi\">:<\/span>\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>$ docker run --rm -it \\\r\n  --mount type=bind,source=\"$(pwd)\"\/inventory,dst=\/inventory \\\r\n  --mount type=bind,source=\"$(pwd)\"\/cluster.yml,dst=\/kubespray\/cluster.yml \\\r\n  --mount type=bind,source=\"${HOME}\"\/.kube,dst=\/root\/.kube \\\r\n  --mount type=bind,source=\"${HOME}\"\/.ssh\/id_rsa,dst=\/root\/.ssh\/id_rsa \\\r\n  quay.io\/kubespray\/kubespray:v2.23.1 bash\r\n\r\n# Inside a container\r\n$ ansible-playbook -i \/inventory\/hosts.yaml cluster.yml\r\n<\/code><\/pre>\n<h4>\u8bbf\u95ee Kubernetes \u96c6\u7fa4<\/h4>\n<p>\u4ece\u4efb\u4e00\u4e3b\u8282\u70b9\u83b7\u53d6\u8ba4\u8bc1\u4fe1\u606f admin.conf\u3002<\/p>\n<pre class=\"post-pre\"><code>$ mkdir -p ~\/.kube\r\n$ scp root@192.168.8.201:\/etc\/kubernetes\/admin.conf ~\/.kube\r\n<\/code><\/pre>\n<p>\u8bf7\u5c06 admin.conf \u6587\u4ef6\u4e2d clusters.cluster.server \u7684 IP \u5730\u5740\u4fee\u6539\u4e3a\u516c\u5171IP\u5730\u5740\uff08\u4f8b\u5982\uff1a192.168.8.201\uff09\uff0c\u539f\u5730\u5740\u4e3a127.0.0.1\u3002<\/p>\n<pre class=\"post-pre\"><code>apiVersion: v1\r\nclusters:\r\n- cluster:\r\n    certificate-authority-data: &lt;CERTIFICATE_AUTHORITY_DATA&gt;\r\n    server: https:\/\/192.168.8.201:6443\r\n  name: cluster.local\r\n...\r\n<\/code><\/pre>\n<p>\u5728.bashrc\u7b49\u6587\u4ef6\u4e2d\u8bbe\u7f6e\u4ee5\u4e0b\u73af\u5883\u53d8\u91cf\u3002<\/p>\n<pre class=\"post-pre\"><code>$ export KUBECONFIG=$HOME\/.kube\/admin.conf \r\n<\/code><\/pre>\n<p>\u901a\u8fc7\u4ee5\u4e0a\u7684\u6b65\u9aa4\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528 kubectl \u8fdb\u5165\u96c6\u7fa4\u3002<\/p>\n<pre class=\"post-pre\"><code>$ kubectl cluster-info\r\nKubernetes control plane is running at https:\/\/192.168.8.201:6443\r\n\r\nTo further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.\r\n\r\n$ kubectl get nodes\r\nNAME           STATUS   ROLES           AGE   VERSION\r\nk8s-master-1   Ready    control-plane   70m   v1.26.5\r\nk8s-worker-1   Ready    &lt;none&gt;          68m   v1.26.5\r\nk8s-worker-2   Ready    &lt;none&gt;          68m   v1.26.5\r\n<\/code><\/pre>\n<hr \/>\n<h2>\u6280\u5de7<\/h2>\n<h3>\u4f7f\u7528Kubespray\u8fdb\u884c\u4ee3\u7406\u914d\u7f6e<\/h3>\n<p>\u5982\u679c\u8981\u8bbe\u7f6e\u4ee3\u7406\uff0c\u8bf7\u7f16\u8f91inventory\/mycluster\/group_vars\/all\/all.yml\u6587\u4ef6\u4e2d\u7684\u4ee5\u4e0b\u9879\u76ee\u3002<\/p>\n<pre class=\"post-pre\"><code>http_proxy: 'http:\/\/your-proxy-server:8080'\r\nhttps_proxy: 'http:\/\/your-proxy-server:8080'\r\nno_proxy: 'localhost,127.0.0.1,.yourdomain.com'\r\n<\/code><\/pre>\n<h3>\u5c06\u81ea\u5df1\u7684playbook\u96c6\u6210\u5230Kubespray\u4e2d\u3002<\/h3>\n<p>\u5982\u679c\u5728\u5e94\u7528cluster.yml\u4e4b\u540e\u9700\u8981\u6267\u884c\u81ea\u5b9a\u4e49\u7684\u9644\u52a0\u5904\u7406\uff0c\u53ef\u4ee5\u8fd9\u6837\u64cd\u4f5c\u3002<\/p>\n<p>\u67e5\u770bKubespray\u7684cluster.yml\u6587\u4ef6\uff0c\u53ef\u4ee5\u770b\u51fa\u53ea\u662f\u7b80\u5355\u5730\u5bfc\u5165\u4e86playbooks\/cluster.yml\u6587\u4ef6\uff0c\u6240\u4ee5\u5982\u679c\u9700\u8981\u6267\u884c\u989d\u5916\u7684\u4efb\u52a1\uff0c\u9700\u8981\u5728cluster.yml\u7684\u672b\u5c3e\u6dfb\u52a0\u5b9a\u5236\u5316\u7684\u5904\u7406\uff0c\u521b\u5efa\u4e00\u4e2a\u540d\u4e3acustomized_cluster.yml\u7684\u6587\u4ef6\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nn\">---<\/span>\r\n<span class=\"c1\"># This role assumes to call Kubespray's `playbooks\/cluster`.<\/span>\r\n<span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Install Kubernetes<\/span>\r\n  <span class=\"na\">ansible.builtin.import_playbook<\/span><span class=\"pi\">:<\/span> <span class=\"s\">playbooks\/cluster.yml<\/span>\r\n\r\n<span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Registernqualified<\/span>\r\n  <span class=\"na\">hosts<\/span><span class=\"pi\">:<\/span> <span class=\"s\">all<\/span>\r\n  <span class=\"na\">tasks<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"pi\">-<\/span> <span class=\"na\">ansible.builtin.file<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">path<\/span><span class=\"pi\">:<\/span> <span class=\"s\">\/etc\/containers\/registries.conf.d<\/span>\r\n        <span class=\"na\">state<\/span><span class=\"pi\">:<\/span> <span class=\"s\">directory<\/span>\r\n        <span class=\"na\">mode<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">0755'<\/span>\r\n    <span class=\"pi\">-<\/span> <span class=\"na\">ansible.builtin.copy<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">dest<\/span><span class=\"pi\">:<\/span> <span class=\"s\">\/etc\/containers\/registries.conf.d\/01-unqualified.conf<\/span>\r\n        <span class=\"na\">content<\/span><span class=\"pi\">:<\/span> <span class=\"pi\">|<\/span>\r\n\r\n          <span class=\"s\">unqualified-search-registries = ['docker.io', 'quay.io']<\/span>\r\n\r\n<span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Download amind.conf to localhost<\/span>\r\n  <span class=\"na\">hosts<\/span><span class=\"pi\">:<\/span> <span class=\"s\">kube_control_plane<\/span>\r\n  <span class=\"na\">run_once<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\r\n  <span class=\"na\">tasks<\/span><span class=\"pi\">:<\/span>\r\n    <span class=\"pi\">-<\/span> <span class=\"na\">ansible.builtin.fetch<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">src<\/span><span class=\"pi\">:<\/span> <span class=\"s\">\/etc\/kubernetes\/admin.conf<\/span>\r\n        <span class=\"na\">dest<\/span><span class=\"pi\">:<\/span> <span class=\"s\">~\/.kube\/admin.conf<\/span>\r\n        <span class=\"na\">flat<\/span><span class=\"pi\">:<\/span> <span class=\"s\">yes<\/span>\r\n    <span class=\"pi\">-<\/span> <span class=\"na\">delegate_to<\/span><span class=\"pi\">:<\/span> <span class=\"s\">localhost<\/span>\r\n      <span class=\"na\">ansible.builtin.replace<\/span><span class=\"pi\">:<\/span>\r\n        <span class=\"na\">path<\/span><span class=\"pi\">:<\/span> <span class=\"s\">~\/.kube\/admin.conf<\/span>\r\n        <span class=\"na\">regexp<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">127.0.0.1'<\/span>\r\n        <span class=\"na\">replace<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">{{<\/span> <span class=\"s\">hostvars[inventory_hostname]['ansible_default_ipv4']['address']<\/span> <span class=\"s\">}}\"<\/span>\r\n<\/code><\/pre>\n<p>\u5728\u4e0a\u9762\u7684\u4f8b\u5b50\u4e2d\uff0c\u4e0b\u4e00\u6b65\u7684\u4efb\u52a1\u662f\u521b\u5efa\u96c6\u7fa4\u3002<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">Unqualified registries (docker.io \u3068 quay.io) \u306e\u8ffd\u52a0<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">admin.conf \u3092\u30ed\u30fc\u30ab\u30eb\u306b\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u3001API \u30b5\u30fc\u30d0\u306e\u30a2\u30c9\u30ec\u30b9\u3092 Public IP \u306b\u7f6e\u63db<\/ul>\n<p>\u5c06\u5176\u81ea\u52a8\u5316\u3002\u53ea\u9700\u5c06Kubespray\u7684cluster.yml\u66ff\u6362\u4e3a\u6b64\u6587\u4ef6\uff0c\u7136\u540e\u6309\u7167\u6b63\u5e38 playbook \u7684\u65b9\u5f0f\u6267\u884c\u5373\u53ef\u3002<\/p>\n<pre class=\"post-pre\"><code>$ docker run --rm -it \\\r\n  --mount type=bind,source=\"$(pwd)\"\/inventory,dst=\/inventory \\\r\n  --mount type=bind,source=\"$(pwd)\"\/.terraform\/modules\/kubernetes\/kubernetes\/generate_inventory.py,dst=\/kubespray\/generate_inventory.py \\\r\n  --mount type=bind,source=\"$(pwd)\"\/terraform.tfstate,dst=\/kubespray\/terraform.tfstate \\\r\n  --mount type=bind,source=\"$(pwd)\"\/cluster.yml,dst=\/kubespray\/cluster.yml \\\r\n  --mount type=bind,source=\"${HOME}\"\/.kube,dst=\/root\/.kube \\\r\n  --mount type=bind,source=\"${HOME}\"\/.ssh\/id_rsa,dst=\/root\/.ssh\/id_rsa \\\r\n  quay.io\/kubespray\/kubespray:v2.23.1 bash\r\n\r\n# Inside a container\r\nansible-playbook -i generate_inventory.py cluster.yml\r\n<\/code><\/pre>\n<p>\u8bf7\u53c2\u8003 kubespray\/docs\/integration.md at master \u00b7 kubernetes-sigs\/kubespray \u00b7 GitHub \u4e2d\u7684\u516c\u5f0f\u6307\u5357\u3002<\/p>\n<h3>\u5728\u79bb\u7ebf\u73af\u5883\u4e0b\u6267\u884c Terraform<\/h3>\n<p>\u901a\u5e38\u60c5\u51b5\u4e0b\uff0cProvider \u662f\u901a\u8fc7\u4e92\u8054\u7f51\u81ea\u52a8\u4e0b\u8f7d\u7684\uff0c\u4f46\u5728\u79bb\u7ebf\u73af\u5883\u4e0b\uff0c\u60a8\u53ef\u4ee5\u5728\u4e3b\u76ee\u5f55\u4e0b\u51c6\u5907\u4e00\u4e2a ~\/terraform.d\/providers \u6587\u4ef6\u5939\uff0c\u5e76\u5c06 Provider \u653e\u5728\u90a3\u91cc\u3002<\/p>\n<p>\u4ee5Terraform Libvirt Provider\u4e3a\u4f8b\uff0c\u4ecedmacvicar\/terraform-provider-libvirt\u7684Releases\u9875\u9762\u4e0b\u8f7d\u4e8c\u8fdb\u5236\u6587\u4ef6\uff0c\u5e76\u6309\u7167\u4ee5\u4e0b\u65b9\u5f0f\u8fdb\u884c\u914d\u7f6e\uff1a<\/p>\n<pre class=\"post-pre\"><code>~\/terraform.d\/providers\/\r\n\u2514\u2500\u2500 providers\/\r\n    \u2514\u2500\u2500 registry.terraform.io\/\r\n        \u2514\u2500\u2500 dmacvicar\/\r\n            \u2514\u2500\u2500 libvirt\/\r\n                \u2514\u2500\u2500 0.7.1\/\r\n                    \u2514\u2500\u2500 linux_amd64\/\r\n                        \u251c\u2500\u2500 CHANGELOG.md\r\n                        \u251c\u2500\u2500 LICENSE\r\n                        \u251c\u2500\u2500 README.md\r\n                        \u2514\u2500\u2500 terraform-provider-libvirt_v0.7.4\r\n<\/code><\/pre>\n<h3>\u5728\u9060\u7a0b\u4e3b\u6a5f\u4e0a\u61c9\u7528 Terraform.<\/h3>\n<p>\u53ef\u4ee5\u4ece\u672c\u5730\u6267\u884cTerraform\uff0c\u5e76\u5728\u8fdc\u7a0b\u4e3b\u673a\u4e0a\u521b\u5efa\u865a\u62df\u673a\u3002<\/p>\n<p>\u9996\u5148\uff0c\u5728\u8fdc\u7a0b\u4e3b\u673a\u4e0a\u5b8c\u6210\u4e3b\u673a\u7684\u9884\u914d\u7f6e\u540e\uff0c\u786e\u8ba4libvirtd\u6b63\u5728\u8fd0\u884c\u3002<\/p>\n<pre class=\"post-pre\"><code># Remote side\r\n$ systemctl status libvirtd\r\n<\/code><\/pre>\n<p>\u901a\u8fc7\u4f7f\u7528 qemu+ssh:\/\/\u534f\u8bae\uff0c\u4ece\u5ba2\u6237\u7aef\u9a8c\u8bc1\u8fde\u63a5\uff1a<\/p>\n<pre class=\"post-pre\"><code># Client side\r\n$ virsh -c qemu+ssh:\/\/&lt;user&gt;@&lt;remote_ip&gt;\/system list\r\n Id   Name   State\r\n--------------------\r\n\r\n<\/code><\/pre>\n<p>\u786e\u8ba4\u540e\uff0c\u5728 main.tf \u6587\u4ef6\u4e2d\u6307\u5b9a\u4ee5\u4e0b\u7684\u8fdc\u7a0b\u4e3b\u673a\u4fe1\u606f\uff0c\u5e76\u5728\u5ba2\u6237\u7aef\u4e0a\u6267\u884c terraform apply\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nx\">locals<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">user_home_directory<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">pathexpand<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"~\"<\/span><span class=\"p\">)<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">provider<\/span> <span class=\"s2\">\"libvirt\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">uri<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"qemu+ssh:\/\/&lt;remote-user&gt;@&lt;remote_host&gt;\/system?keyfile=${local.user_home_directory}\/.ssh\/id_rsa&amp;known_hosts_verify=ignore\"<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<h4>\u5982\u679c\u901a\u8fc7\u8df3\u677f\u670d\u52a1\u5668\u7684\u8bdd<\/h4>\n<p>\u5f53\u901a\u8fc7\u8df3\u677f\u670d\u52a1\u5668\u8fdc\u7a0b\u8bbf\u95ee\u65f6\uff0c\u9700\u8981\u5c06\u8fdc\u7a0b\u768422\u7aef\u53e3\u8f6c\u53d1\u5230\u672c\u5730\u7684\u4e00\u4e2a\u9002\u5f53\u7aef\u53e3\uff08\u4f8b\u5982\uff1a50000\uff09\u3002<\/p>\n<pre class=\"post-pre\"><code># Client side\r\n$ ssh -C -N -f -L 50000:&lt;remote-user&gt;@&lt;remote-host&gt;:22 &lt;bastion-host&gt; -p &lt;bastion-port&gt;\r\n$ virsh -c qemu+ssh:\/\/&lt;remote-user&gt;@localhost:50000\/system list\r\n Id   Name   State\r\n--------------------\r\n\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code><span class=\"nx\">locals<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">user_home_directory<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">pathexpand<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"~\"<\/span><span class=\"p\">)<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">provider<\/span> <span class=\"s2\">\"libvirt\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">uri<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"qemu+ssh:\/\/&lt;remote-user&gt;@localhost:50000\/system?keyfile=${local.user_home_directory}\/.ssh\/id_rsa&amp;known_hosts_verify=ignore\"<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<h3>\u5c06\u8fd9\u7bc7\u6587\u7ae0\u4e2d\u7684 Terraform \u4ee3\u7801\u4f5c\u4e3a\u6a21\u5757\u4f7f\u7528<\/h3>\n<p>\u51c6\u5907\u4e00\u4e2a\u5982\u4e0b\u7684 main.tf \u6587\u4ef6\u3002\u5728\u8fd9\u4e2a\u4f8b\u5b50\u4e2d\uff0c\u5c06\u521b\u5efa\u4e00\u4e2a\u75311\u4e2a\u4e3b\u8282\u70b9\u548c2\u4e2a\u5de5\u4f5c\u8282\u70b9\u7ec4\u6210\u7684\u5171\u8ba13\u53f0\u865a\u62df\u673a\uff08VM\uff09\uff0c\u4f46\u8bf7\u6839\u636e\u6240\u9700\u7684\u914d\u7f6e\u9002\u5f53\u4fee\u6539\u53c2\u6570\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nx\">output<\/span> <span class=\"s2\">\"kubespray_hosts\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">value<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">module<\/span><span class=\"p\">.<\/span><span class=\"nx\">kubernetes<\/span><span class=\"p\">.<\/span><span class=\"nx\">kubespray_hosts<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">output<\/span> <span class=\"s2\">\"libvirt_uri\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">value<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">module<\/span><span class=\"p\">.<\/span><span class=\"nx\">kubernetes<\/span><span class=\"p\">.<\/span><span class=\"nx\">libvirt_uri<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">locals<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">user_home_directory<\/span> <span class=\"p\">=<\/span> <span class=\"nx\">pathexpand<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"~\"<\/span><span class=\"p\">)<\/span>\r\n<span class=\"p\">}<\/span>\r\n\r\n<span class=\"nx\">module<\/span> <span class=\"s2\">\"kubernetes\"<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"nx\">source<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"github.com\/sawa2d2\/k8s-on-kvm\/\/kubernetes\/\"<\/span>\r\n\r\n  <span class=\"c1\">## Localhost:<\/span>\r\n  <span class=\"c1\"># libvirt_uri = \"qemu:\/\/\/system\"<\/span>\r\n  <span class=\"c1\">## Remote:<\/span>\r\n  <span class=\"c1\"># libvirt_uri = \"qemu+ssh:\/\/&lt;user&gt;@&lt;remote-host&gt;\/system?keyfile=${local.user_home_directory}\/.ssh\/id_rsa&amp;known_hosts_verify=ignore\"<\/span>\r\n  <span class=\"c1\">## Remote via bastion:<\/span>\r\n  <span class=\"c1\">##   Forward port in advance.<\/span>\r\n  <span class=\"c1\">##   $ ssh -C -N -f -L 50000:&lt;remote-user&gt;@&lt;remote-host&gt;:22 &lt;bastion-host&gt; -p &lt;bastion-port&gt;<\/span>\r\n  <span class=\"c1\"># libvirt_uri = \"qemu+ssh:\/\/&lt;remote-user&gt;@localhost:50000\/system?keyfile=${local.user_home_directory}\/.ssh\/id_rsa&amp;known_hosts_verify=ignore\"<\/span>\r\n  <span class=\"nx\">libvirt_uri<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"qemu:\/\/\/system\"<\/span>\r\n\r\n  <span class=\"c1\"># Download the image by:<\/span>\r\n  <span class=\"c1\">#   sudo curl -L -o \/var\/lib\/libvirt\/images\/Rocky-9-GenericCloud.latest.x86_64.qcow2 https:\/\/download.rockylinux.org\/pub\/rocky\/9.2\/images\/x86_64\/Rocky-9-GenericCloud.latest.x86_64.qcow2 <\/span>\r\n  <span class=\"nx\">vm_base_image_uri<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"\/var\/lib\/libvirt\/images\/Rocky-9-GenericCloud.latest.x86_64.qcow2\"<\/span>\r\n  <span class=\"nx\">pool<\/span>              <span class=\"p\">=<\/span> <span class=\"s2\">\"default\"<\/span>\r\n\r\n  <span class=\"c1\"># Cluster network<\/span>\r\n  <span class=\"nx\">bridge<\/span>      <span class=\"p\">=<\/span> <span class=\"s2\">\"br0\"<\/span>\r\n  <span class=\"nx\">cidr<\/span>        <span class=\"p\">=<\/span> <span class=\"s2\">\"192.168.8.0\/24\"<\/span>\r\n  <span class=\"nx\">gateway<\/span>     <span class=\"p\">=<\/span> <span class=\"s2\">\"192.168.8.1\"<\/span>\r\n  <span class=\"nx\">nameservers<\/span> <span class=\"p\">=<\/span> <span class=\"p\">[<\/span><span class=\"s2\">\"192.168.8.1\"<\/span><span class=\"p\">]<\/span>\r\n\r\n  <span class=\"nx\">vms<\/span> <span class=\"p\">=<\/span> <span class=\"p\">[<\/span>\r\n    <span class=\"p\">{<\/span>\r\n      <span class=\"nx\">name<\/span>           <span class=\"p\">=<\/span> <span class=\"s2\">\"k8s-master-1\"<\/span>\r\n      <span class=\"nx\">vcpu<\/span>           <span class=\"p\">=<\/span> <span class=\"mi\">4<\/span>\r\n      <span class=\"nx\">memory<\/span>         <span class=\"p\">=<\/span> <span class=\"mi\">16000<\/span>                    <span class=\"c1\"># in MiB<\/span>\r\n      <span class=\"nx\">disk<\/span>           <span class=\"p\">=<\/span> <span class=\"mi\">100<\/span> <span class=\"p\">*<\/span> <span class=\"mi\">1024<\/span> <span class=\"p\">*<\/span> <span class=\"mi\">1024<\/span> <span class=\"p\">*<\/span> <span class=\"mi\">1024<\/span> <span class=\"c1\"># 100 GB<\/span>\r\n      <span class=\"nx\">public_ip<\/span>      <span class=\"p\">=<\/span> <span class=\"s2\">\"192.168.8.101\"<\/span>\r\n      <span class=\"nx\">private_ip<\/span>     <span class=\"p\">=<\/span> <span class=\"s2\">\"192.168.122.201\"<\/span>\r\n      <span class=\"nx\">cloudinit_file<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"cloud_init.cfg\"<\/span>\r\n      <span class=\"nx\">volumes<\/span>        <span class=\"p\">=<\/span> <span class=\"p\">[]<\/span>\r\n\r\n      <span class=\"nx\">kube_control_plane<\/span> <span class=\"p\">=<\/span> <span class=\"kc\">true<\/span>\r\n      <span class=\"nx\">kube_node<\/span>          <span class=\"p\">=<\/span> <span class=\"kc\">true<\/span>\r\n      <span class=\"nx\">etcd<\/span>               <span class=\"p\">=<\/span> <span class=\"kc\">true<\/span>\r\n    <span class=\"p\">},<\/span>\r\n    <span class=\"p\">{<\/span>\r\n      <span class=\"nx\">name<\/span>           <span class=\"p\">=<\/span> <span class=\"s2\">\"k8s-worker-1\"<\/span>\r\n      <span class=\"nx\">vcpu<\/span>           <span class=\"p\">=<\/span> <span class=\"mi\">4<\/span>\r\n      <span class=\"nx\">memory<\/span>         <span class=\"p\">=<\/span> <span class=\"mi\">16000<\/span>                    <span class=\"c1\"># in MiB<\/span>\r\n      <span class=\"nx\">disk<\/span>           <span class=\"p\">=<\/span> <span class=\"mi\">100<\/span> <span class=\"p\">*<\/span> <span class=\"mi\">1024<\/span> <span class=\"p\">*<\/span> <span class=\"mi\">1024<\/span> <span class=\"p\">*<\/span> <span class=\"mi\">1024<\/span> <span class=\"c1\"># 100 GB<\/span>\r\n      <span class=\"nx\">public_ip<\/span>      <span class=\"p\">=<\/span> <span class=\"s2\">\"192.168.8.102\"<\/span>\r\n      <span class=\"nx\">private_ip<\/span>     <span class=\"p\">=<\/span> <span class=\"s2\">\"192.168.122.202\"<\/span>\r\n      <span class=\"nx\">cloudinit_file<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"cloud_init.cfg\"<\/span>\r\n      <span class=\"nx\">volumes<\/span>        <span class=\"p\">=<\/span> <span class=\"p\">[]<\/span>\r\n\r\n      <span class=\"nx\">kube_control_plane<\/span> <span class=\"p\">=<\/span> <span class=\"kc\">false<\/span>\r\n      <span class=\"nx\">kube_node<\/span>          <span class=\"p\">=<\/span> <span class=\"kc\">true<\/span>\r\n      <span class=\"nx\">etcd<\/span>               <span class=\"p\">=<\/span> <span class=\"kc\">false<\/span>\r\n    <span class=\"p\">},<\/span>\r\n    <span class=\"p\">{<\/span>\r\n      <span class=\"nx\">name<\/span>           <span class=\"p\">=<\/span> <span class=\"s2\">\"k8s-worker-2\"<\/span>\r\n      <span class=\"nx\">vcpu<\/span>           <span class=\"p\">=<\/span> <span class=\"mi\">2<\/span>\r\n      <span class=\"nx\">memory<\/span>         <span class=\"p\">=<\/span> <span class=\"mi\">8000<\/span>                     <span class=\"c1\"># in MiB<\/span>\r\n      <span class=\"nx\">disk<\/span>           <span class=\"p\">=<\/span> <span class=\"mi\">100<\/span> <span class=\"p\">*<\/span> <span class=\"mi\">1024<\/span> <span class=\"p\">*<\/span> <span class=\"mi\">1024<\/span> <span class=\"p\">*<\/span> <span class=\"mi\">1024<\/span> <span class=\"c1\"># 100 GB<\/span>\r\n      <span class=\"nx\">public_ip<\/span>      <span class=\"p\">=<\/span> <span class=\"s2\">\"192.168.8.103\"<\/span>\r\n      <span class=\"nx\">private_ip<\/span>     <span class=\"p\">=<\/span> <span class=\"s2\">\"192.168.122.203\"<\/span>\r\n      <span class=\"nx\">cloudinit_file<\/span> <span class=\"p\">=<\/span> <span class=\"s2\">\"cloud_init.cfg\"<\/span>\r\n      <span class=\"nx\">volumes<\/span>        <span class=\"p\">=<\/span> <span class=\"p\">[]<\/span>\r\n\r\n      <span class=\"nx\">kube_control_plane<\/span> <span class=\"p\">=<\/span> <span class=\"kc\">false<\/span>\r\n      <span class=\"nx\">kube_node<\/span>          <span class=\"p\">=<\/span> <span class=\"kc\">true<\/span>\r\n      <span class=\"nx\">etcd<\/span>               <span class=\"p\">=<\/span> <span class=\"kc\">false<\/span>\r\n    <span class=\"p\">},<\/span>\r\n  <span class=\"p\">]<\/span>\r\n<span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<h2>\u4ee5\u4e0b\u662f\u53c2\u8003\u8d44\u6599<\/h2>\n<h3>Terraform \u548c Dynamic Inventory \u76f8\u5173<\/h3>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">End-to-End Application Provisioning with Ansible and Terraform &#8211; IBM Blog<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">Integrating Ansible and Jenkins with Terraform to make a powerful infrastructure | by Ankush Chavan | Medium<\/ul>\n<h3>libvirt\u7684\u914d\u7f6e\u76f8\u5173<\/h3>\n<p>error when default storage pool is missing \u00b7 Issue #8 \u00b7 simon3z\/virt-deploy &#8230; default pool \u306e\u4f5c\u6210\u65b9\u6cd5\u306a\u3069<\/p>\n<h3>\u5173\u4e8eKuberspray\u7684\u76f8\u5173\u5185\u5bb9<\/h3>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">kubespray\u3092\u4f7f\u3063\u305fKubernetes\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb | Kubernetes<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">An introduction to Kubespray | Enable Sysadmin<\/ul>\n<h3>\u6865\u6881\u8bbe\u7f6e\u76f8\u5173<\/h3>\n<ul class=\"post-ul\">KVM\u3067\u30b2\u30b9\u30c8OS\u3092\u30d6\u30ea\u30c3\u30b8\u63a5\u7d9a\u3059\u308b &#8211; Qiita<\/ul>\n<h2>\u76f8\u5173\u6587\u7ae0<\/h2>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u592a\u957f\u4e0d\u8bfb b\u00f9 d\u00fa) \u5728\u5b9a\u4e49\u4e86\u7ec4\u6210\u4e4b\u540e\uff0c\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u547d\u4ee4\u521b\u5efa Kubernetes \u96c6\u7fa4\uff1a $ terraf [&hellip;]<\/p>\n","protected":false},"author":8,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-48849","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.5 (Yoast SEO v21.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>\u4f7f\u7528Terraform + Kubespray\u5728KVM\u4e0a\u6784\u5efaKubernetes\u96c6\u7fa4 - Blog - Silicon Cloud<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528terraform-kubespray\u5728kvm\u4e0a\u6784\u5efakubernetes\u96c6\u7fa4\u3002\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u4f7f\u7528Terraform + Kubespray\u5728KVM\u4e0a\u6784\u5efaKubernetes\u96c6\u7fa4\" \/>\n<meta property=\"og:description\" content=\"\u592a\u957f\u4e0d\u8bfb b\u00f9 d\u00fa) \u5728\u5b9a\u4e49\u4e86\u7ec4\u6210\u4e4b\u540e\uff0c\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u547d\u4ee4\u521b\u5efa Kubernetes \u96c6\u7fa4\uff1a $ terraf [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528terraform-kubespray\u5728kvm\u4e0a\u6784\u5efakubernetes\u96c6\u7fa4\u3002\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog - Silicon Cloud\" \/>\n<meta property=\"article:published_time\" content=\"2023-11-06T15:33:36+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-29T13:14:31+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d87c2913a08637a6c0c09\/8-0.png\" \/>\n<meta name=\"author\" content=\"\u96c5, \u609f\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u96c5, \u609f\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/\",\"name\":\"\u4f7f\u7528Terraform + Kubespray\u5728KVM\u4e0a\u6784\u5efaKubernetes\u96c6\u7fa4 - Blog - Silicon Cloud\",\"isPartOf\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\"},\"datePublished\":\"2023-11-06T15:33:36+00:00\",\"dateModified\":\"2024-04-29T13:14:31+00:00\",\"author\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/f044a4b7fa4ee2701702942002419ca6\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.silicloud.com\/zh\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u4f7f\u7528Terraform + Kubespray\u5728KVM\u4e0a\u6784\u5efaKubernetes\u96c6\u7fa4\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/\",\"name\":\"Blog - Silicon Cloud\",\"description\":\"\",\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/f044a4b7fa4ee2701702942002419ca6\",\"name\":\"\u96c5, \u609f\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/e71a913e914f1aad1efc391f92084294bac54bc782acd289638580134cf667a6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/e71a913e914f1aad1efc391f92084294bac54bc782acd289638580134cf667a6?s=96&d=mm&r=g\",\"caption\":\"\u96c5, \u609f\"},\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/author\/yawu\/\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/#local-main-organization-logo\",\"url\":\"\",\"contentUrl\":\"\",\"caption\":\"Blog - Silicon Cloud\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"\u4f7f\u7528Terraform + Kubespray\u5728KVM\u4e0a\u6784\u5efaKubernetes\u96c6\u7fa4 - Blog - Silicon Cloud","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528terraform-kubespray\u5728kvm\u4e0a\u6784\u5efakubernetes\u96c6\u7fa4\u3002\/","og_locale":"zh_CN","og_type":"article","og_title":"\u4f7f\u7528Terraform + Kubespray\u5728KVM\u4e0a\u6784\u5efaKubernetes\u96c6\u7fa4","og_description":"\u592a\u957f\u4e0d\u8bfb b\u00f9 d\u00fa) \u5728\u5b9a\u4e49\u4e86\u7ec4\u6210\u4e4b\u540e\uff0c\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u547d\u4ee4\u521b\u5efa Kubernetes \u96c6\u7fa4\uff1a $ terraf [&hellip;]","og_url":"https:\/\/www.silicloud.com\/zh\/blog\/\u4f7f\u7528terraform-kubespray\u5728kvm\u4e0a\u6784\u5efakubernetes\u96c6\u7fa4\u3002\/","og_site_name":"Blog - Silicon Cloud","article_published_time":"2023-11-06T15:33:36+00:00","article_modified_time":"2024-04-29T13:14:31+00:00","og_image":[{"url":"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d87c2913a08637a6c0c09\/8-0.png"}],"author":"\u96c5, \u609f","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"\u96c5, \u609f","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"13 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/","url":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/","name":"\u4f7f\u7528Terraform + Kubespray\u5728KVM\u4e0a\u6784\u5efaKubernetes\u96c6\u7fa4 - Blog - Silicon Cloud","isPartOf":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website"},"datePublished":"2023-11-06T15:33:36+00:00","dateModified":"2024-04-29T13:14:31+00:00","author":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/f044a4b7fa4ee2701702942002419ca6"},"breadcrumb":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.silicloud.com\/zh\/blog\/"},{"@type":"ListItem","position":2,"name":"\u4f7f\u7528Terraform + Kubespray\u5728KVM\u4e0a\u6784\u5efaKubernetes\u96c6\u7fa4"}]},{"@type":"WebSite","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website","url":"https:\/\/www.silicloud.com\/zh\/blog\/","name":"Blog - Silicon Cloud","description":"","inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/f044a4b7fa4ee2701702942002419ca6","name":"\u96c5, \u609f","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/e71a913e914f1aad1efc391f92084294bac54bc782acd289638580134cf667a6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e71a913e914f1aad1efc391f92084294bac54bc782acd289638580134cf667a6?s=96&d=mm&r=g","caption":"\u96c5, \u609f"},"url":"https:\/\/www.silicloud.com\/zh\/blog\/author\/yawu\/"},{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bd%bf%e7%94%a8terraform-kubespray%e5%9c%a8kvm%e4%b8%8a%e6%9e%84%e5%bb%bakubernetes%e9%9b%86%e7%be%a4%e3%80%82\/#local-main-organization-logo","url":"","contentUrl":"","caption":"Blog - Silicon Cloud"}]}},"_links":{"self":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/48849","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/comments?post=48849"}],"version-history":[{"count":2,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/48849\/revisions"}],"predecessor-version":[{"id":87678,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/48849\/revisions\/87678"}],"wp:attachment":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/media?parent=48849"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/categories?post=48849"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/tags?post=48849"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}