我已经开发了一个terraform脚本,在GKE上创建k8集群。
在成功创建集群后,我有一组yaml文件需要应用到k8集群中。
我如何在我的terraform脚本中调用下面的命令?
kubectl create <.yaml>
我已经开发了一个terraform脚本,在GKE上创建k8集群。
在成功创建集群后,我有一组yaml文件需要应用到k8集群中。
我如何在我的terraform脚本中调用下面的命令?
kubectl create <.yaml>
kubectl
。请按照这里的安装说明进行操作:Kubectl Terraform Provider。然后,只需定义一个指向你的 YAML 文件的kubectl_manifest
就行了。# Get your cluster-info
data "google_container_cluster" "my_cluster" {
name = "my-cluster"
location = "us-east1-a"
}
# Same parameters as kubernetes provider
provider "kubectl" {
load_config_file = false
host = "https://${data.google_container_cluster.my_cluster.endpoint}"
token = "${data.google_container_cluster.my_cluster.access_token}"
cluster_ca_certificate = "${base64decode(data.google_container_cluster.my_cluster.master_auth.0.cluster_ca_certificate)}"
}
resource "kubectl_manifest" "my_service" {
yaml_body = file("${path.module}/my_service.yaml")
}
这种方法的最大优点在于一切都是动态获取的,不依赖于任何本地配置文件(如果您在CI/CD服务器上运行Terraform或管理多集群环境,则非常重要)。
多对象清单文件
kubectl
提供程序还提供了数据源,可以轻松处理具有多个对象的文件。来自文档kubectl_filename_list:
data "kubectl_filename_list" "manifests" {
pattern = "./manifests/*.yaml"
}
resource "kubectl_manifest" "test" {
count = length(data.kubectl_filename_list.manifests.matches)
yaml_body = file(element(data.kubectl_filename_list.manifests.matches, count.index))
}
额外加分点: 您可以将您的yaml
文件进行模板化处理。我在多资源自动缩放器 yaml 文件中插入集群名称的方法如下:
resource "kubectl_manifest" "autoscaler" {
yaml_body = templatefile("${path.module}/autoscaler.yaml", {cluster_name = var.cluster_name })
}
有几种方法可以实现您想要做的事情。
您可以使用 Terraform 资源 template_file 和 null_resource。
请注意,我正在使用 trigger 来运行 kubectl 命令,每次修改模板时都会运行它(您可能需要将 create 替换为 apply)。
data "template_file" "your_template" {
template = "${file("${path.module}/templates/<.yaml>")}"
}
resource "null_resource" "your_deployment" {
triggers = {
manifest_sha1 = "${sha1("${data.template_file.your_template.rendered}")}"
}
provisioner "local-exec" {
command = "kubectl create -f -<<EOF\n${data.template_file.your_template.rendered}\nEOF"
}
}
但是也许最好的方法是使用Kubernetes提供程序。
有两种配置方式:
kubectl config current-context
)provider "kubernetes" {
host = "https://104.196.242.174"
client_certificate = "${file("~/.kube/client-cert.pem")}"
client_key = "${file("~/.kube/client-key.pem")}"
cluster_ca_certificate = "${file("~/.kube/cluster-ca-cert.pem")}"
}
完成上述步骤后,您可以轻松创建自己的部署。对于基本Pod,只需执行以下操作:
resource "kubernetes_pod" "hello_world" {
metadata {
name = "hello-world"
}
spec {
container {
image = "my_account/hello-world:1.0.0"
name = "hello-world"
}
image_pull_secrets {
name = "docker-hub"
}
}
}
exit status 1. Output: << was unexpected at this time.
- christopher clarkdata "template_file" "your_template" {
template = "${file("${path.module}/templates/ingress.yaml")}"
}
- christopher clarkcount
)。如果源文件被更新,Kubernetes 资源的顺序发生变化,可能会导致 Terraform 因索引更改而删除/创建资源。以下代码通过连接 kind
和 metadata.name
字段来创建键:data "kubectl_file_documents" "myk8s" {
content = file("./myk8s.yaml")
}
resource "kubectl_manifest" "myk8s" {
# Create a map of { "kind--name" => raw_yaml }
for_each = {
for value in [
for v in data.kubectl_file_documents.myk8s.documents : [yamldecode(v), v]
] : "${value.0["kind"]}--${value.0["metadata"]["name"]}" => value.1
}
yaml_body = each.value
}
resource "kubernetes_manifest" "default" {
for_each = {
for value in [
for yaml in split(
"\n---\n",
"\n${replace(file("./myk8s.yaml"), "/(?m)^---[[:blank:]]*(#.*)?$/", "---")}\n"
) :
yamldecode(yaml)
if trimspace(replace(yaml, "/(?m)(^[[:blank:]]*(#.*)?$)+/", "")) != ""
] : "${value["kind"]}--${value["metadata"]["name"]}" => value
}
manifest = each.value
}
resource "null_resource" "controller_rancher_installation" {
provisioner "local-exec" {
command = <<EOT
echo "Downloading rancher config"
curl -L https://some-url.yaml -o rancherconfig.yaml
EOT
}
}
data "kubectl_path_documents" "rancher_manifests" {
pattern = "./rancherconfig.yaml"
depends_on = [null_resource.controller_rancher_installation]
}
resource "kubectl_manifest" "spot_cluster_controller" {
count = length(data.kubectl_path_documents.spot_controller_manifests.documents)
yaml_body = element(data.kubectl_path_documents.spot_controller_manifests.documents, count.index)
}
首先需要下载它,然后再应用。这是基于观察得出的结论:
pattern = "./rancherconfig.yaml"
不支持远程url,只能使用本地文件。"kubectl_manifest"
默认只应用yaml文件中的第一个配置/对象。为2022年的观众添加一些现有答案的信息。给定的问题缺少关于这些terraform和kubectl命令需要在哪里执行的信息。
情况1:开发人员使用的是不属于Google Cloud Platform的本地系统
在这种情况下,当您使用null_resource
来执行命令时,您的命令将在本地计算机上而不是Google Cloud上运行。
情况2:开发人员使用的是Google Cloud平台的一部分的系统,例如Google控制台终端或Google Cloud Code
在这种情况下,当您使用null_resource
来执行命令时,您的命令将在一个临时环境中运行,该环境由Google Cloud主动管理。
从这里开始,可以使用terraform执行kubectl
命令。话虽如此,下一个问题是这样做是否是一个好方法?不是。
GCP不是免费资源。如果您正在构建/使用工具,则重要的是针对正确的资源使用正确的工具。在DevOps操作中,有两个核心领域。一个是设置基础架构,其中Terraform最有效,下一个是管理基础架构,其中Ansible最有效。出于同样的原因,GCP积极提供对这些的支持。
你也可以将helm提供程序与itscontained图表一起使用。例如,Tekton仪表板可以像这样安装,在Yuri的Yaml拆分表达式的基础上构建:
data "http" "tekton_dashboard_install" {
url = "https://storage.googleapis.com/tekton-releases/dashboard/previous/v0.26.0/tekton-dashboard-release.yaml"
request_headers = {
Accept = "application/octet-stream"
}
}
locals {
tekton_dashboard_manifests = [
for yaml in split(
"\n---\n",
"\n${replace(data.http.tekton_dashboard_install.body, "/(?m)^---[[:blank:]]*(#.*)?$/", "---")}\n"
) :
yamldecode(yaml)
if trimspace(replace(yaml, "/(?m)(^[[:blank:]]*(#.*)?$)+/", "")) != ""
]
}
resource "helm_release" "tekton_dashboard" {
name = "tekton_dashboard"
repository = "https://charts.itscontained.io"
chart = "raw"
version = "0.2.5"
namespace = "tekton-pipelines"
values = [
yamlencode({ resources = local.tekton_dashboard_manifests })
]
}
resource "aws_instance" "web" {
# ...
provisioner "local-exec" {
command = "echo ${aws_instance.web.private_ip} >> private_ips.txt"
}
}
参考:https://www.terraform.io/docs/provisioners/local-exec.html
terraform fmt
命令使其格式化。 - ydaetskcoR这里的答案都很好。一个建议是,随着您的需求从初始清单发展,您可能需要查看是否可以从清单创建helm图表(或者可能已经存在),并使用terraform helm提供程序来设置环境的值。
https://tech.paulcz.net/blog/getting-started-with-helm/
你会注意到使用Helm提供程序的优点是,它易于通过terraform环境覆盖和管理值的更改,而不是将其嵌入清单中。https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release
最好的方法是使用Terraform的Kubernetes提供程序
kubectl
提供者未发布到注册表中,因此它失败了。我该如何克服这个问题? - Shawlztoken = data.google_client_config.default.access_token
- 请参阅 https://www.terraform.io/docs/providers/google/d/client_config.html。 - rantoniukterraform { required_version = ">= 0.13.3" required_providers { kubectl = { source = "gavinbunney/kubectl" version = ">= 1.7.0" } } }
- rantoniukkubectl_filename_list
数据将它们拆分。请参考上面的示例。我还更新了链接。 - david_g