Добавлен код и промты.
This commit is contained in:
24
.cascade-config.json
Normal file
24
.cascade-config.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"project": {
|
||||||
|
"name": "apk-deploy",
|
||||||
|
"description": "Kubernetes deployment system using Terraform and k3s",
|
||||||
|
"context_files": [
|
||||||
|
"README.md",
|
||||||
|
"environment.md",
|
||||||
|
"project.config",
|
||||||
|
"terraform/terraformrc"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"environment": {
|
||||||
|
"os": ["ubuntu-24.04", "windows-11"],
|
||||||
|
"shell_windows": "git-bash",
|
||||||
|
"required_tools": ["terraform", "ssh", "git"]
|
||||||
|
},
|
||||||
|
"preferences": {
|
||||||
|
"deploy_method": "terraform",
|
||||||
|
"kubernetes": {
|
||||||
|
"version": "v1.31.6+k3s1",
|
||||||
|
"channel": "stable"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
.gitignore
vendored
Normal file
53
.gitignore
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# Ignore Go build and test files
|
||||||
|
_gopath/
|
||||||
|
*.test
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
# Ignore Terraform files
|
||||||
|
.terraform/
|
||||||
|
terraform.tfstate
|
||||||
|
terraform.tfstate.backup
|
||||||
|
*terraform.lock.*
|
||||||
|
*.terraform.tfstate.lock.info
|
||||||
|
|
||||||
|
# Ignore task start time file
|
||||||
|
task_start_time.tmp
|
||||||
|
|
||||||
|
# Ignore vendor directory
|
||||||
|
vendor/
|
||||||
|
|
||||||
|
# Ignore node_modules directory
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Ignore logs directory
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# Ignore OS files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Ignore temporary files
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Ignore backup files
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Ignore token.txt
|
||||||
|
token.txt
|
||||||
|
|
||||||
|
# Ignore k3s config
|
||||||
|
k3s.yaml
|
||||||
|
|
||||||
|
# Ignore environment variables
|
||||||
|
.env
|
||||||
|
|
||||||
|
# windsurf rules
|
||||||
|
.windsurfrules
|
||||||
|
|
||||||
|
# Ignore temporary files
|
||||||
|
**/tmp/**
|
||||||
18
ai-instructions.md
Normal file
18
ai-instructions.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Инструкции для AI при работе с проектом
|
||||||
|
|
||||||
|
## Обязательные файлы для анализа
|
||||||
|
- README.md — базовые сведения о проекте
|
||||||
|
- environment.md — требования к окружению
|
||||||
|
- project.config — важные параметры
|
||||||
|
- terraform/terraformrc — конфигурация Terraform
|
||||||
|
|
||||||
|
## Учитывать особенности
|
||||||
|
1. Проект работает на Ubuntu 24.04 и Windows 11
|
||||||
|
2. На Windows используйте Git Bash
|
||||||
|
3. SSH-ключи хранятся в ~/.ssh/id_rsa
|
||||||
|
4. Версия Kubernetes: v1.31.6+k3s1
|
||||||
|
|
||||||
|
## При ответах всегда
|
||||||
|
- Проверяйте совместимость с обеими ОС
|
||||||
|
- Предлагайте команды для Git Bash в Windows
|
||||||
|
- Учитывайте структуру проекта из README.md
|
||||||
27
environment.md
Normal file
27
environment.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Окружение проекта
|
||||||
|
|
||||||
|
## Поддерживаемые операционные системы
|
||||||
|
- Ubuntu 24.04
|
||||||
|
- Windows 11
|
||||||
|
|
||||||
|
## Требуемые инструменты
|
||||||
|
- Git Bash (для Windows)
|
||||||
|
- Terraform 1.11.0+
|
||||||
|
- SSH доступ к серверам
|
||||||
|
- Kubeconfig для управления кластером
|
||||||
|
|
||||||
|
## Особенности запуска
|
||||||
|
- Все команды терминала должны выполняться в Git Bash на Windows
|
||||||
|
- SSH ключи должны находиться в ~/.ssh/id_rsa
|
||||||
|
- В Windows рекомендуется использовать абсолютные пути для файлов конфигурации
|
||||||
|
|
||||||
|
## Настройки Terraform
|
||||||
|
- Все переменные хранятся в terraform.tfvars
|
||||||
|
- Kubernetes версия k3s: v1.31.6+k3s1
|
||||||
|
- Используется канал обновлений: stable
|
||||||
|
|
||||||
|
## Доступ к серверам
|
||||||
|
- Server IP: reg.benadis.org
|
||||||
|
- Worker IPs: worker1.benadis.org, worker2.benadis.org
|
||||||
|
- User: root
|
||||||
|
- Authentication: SSH key
|
||||||
12
project.config
Normal file
12
project.config
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Конфигурация проекта
|
||||||
|
OS_SUPPORT=ubuntu-24.04,windows-11
|
||||||
|
SHELL_WINDOWS=git-bash
|
||||||
|
TERRAFORM_VERSION=1.11.0+
|
||||||
|
SSH_KEY_PATH=~/.ssh/id_rsa
|
||||||
|
K8S_VERSION=v1.31.6+k3s1
|
||||||
|
K8S_CHANNEL=stable
|
||||||
|
|
||||||
|
# Информация о серверах
|
||||||
|
SERVER_HOST=reg.benadis.org
|
||||||
|
WORKER_HOSTS=worker1.benadis.org,worker2.benadis.org
|
||||||
|
SSH_USER=root
|
||||||
119
terraform/README.md
Normal file
119
terraform/README.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# K3s Kubernetes Cluster Terraform Project
|
||||||
|
|
||||||
|
This Terraform project allows you to deploy a lightweight K3s Kubernetes cluster on any infrastructure that supports SSH access. The project uses only the null and local providers, performing all operations via SSH connections and local/remote execution provisioners.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
terraform/
|
||||||
|
├── modules/
|
||||||
|
│ └── k3s-install/
|
||||||
|
│ ├── main.tf # K3s installation logic
|
||||||
|
│ ├── variables.tf # Module variables
|
||||||
|
│ └── outputs.tf # Module outputs
|
||||||
|
└── infra/
|
||||||
|
└── dev/
|
||||||
|
├── main.tf # Main entry point
|
||||||
|
├── variables.tf # Variable definitions
|
||||||
|
├── terraform.tfvars # Variable values
|
||||||
|
├── env.tf # Environment file handling
|
||||||
|
├── providers.tf # Provider configurations
|
||||||
|
└── .env # Environment variables (template)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. SSH access to all target nodes (server and workers)
|
||||||
|
2. SSH key pair for authentication
|
||||||
|
3. Terraform >= 1.0.0
|
||||||
|
4. Target nodes with:
|
||||||
|
- A supported operating system (Ubuntu, Debian, CentOS, etc.)
|
||||||
|
- Sufficient privileges to install system packages
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Setting Up Variables
|
||||||
|
|
||||||
|
1. Edit `terraform/infra/dev/terraform.tfvars` to configure your infrastructure:
|
||||||
|
- Set `server_ip` to the IP address of your K3s server node
|
||||||
|
- Set `worker_ips` to a list of IP addresses for your worker nodes
|
||||||
|
- Set `ssh_user` to the SSH username for connecting to the nodes
|
||||||
|
- Set `ssh_private_key` to the path of your SSH private key
|
||||||
|
- Customize other parameters as needed
|
||||||
|
|
||||||
|
2. Alternatively, you can use environment variables by editing the `.env` file:
|
||||||
|
- Uncomment and set the desired variables
|
||||||
|
- Variables defined in `.env` will override those in `terraform.tfvars`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Deploying the Cluster
|
||||||
|
|
||||||
|
Navigate to the deployment directory and initialize Terraform:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cd terraform/infra/dev
|
||||||
|
terraform init
|
||||||
|
```
|
||||||
|
|
||||||
|
Review the execution plan:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform plan
|
||||||
|
```
|
||||||
|
|
||||||
|
Apply the configuration to deploy the K3s cluster:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform apply
|
||||||
|
```
|
||||||
|
|
||||||
|
### Accessing the Cluster
|
||||||
|
|
||||||
|
After deployment, the kubeconfig will be available at the path specified by `kubeconfig_path` (default: `~/.kube/config`). You can use this to interact with your cluster:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl get nodes
|
||||||
|
kubectl get pods --all-namespaces
|
||||||
|
```
|
||||||
|
|
||||||
|
### Destroying the Cluster
|
||||||
|
|
||||||
|
To tear down the cluster:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform destroy
|
||||||
|
```
|
||||||
|
|
||||||
|
This will uninstall K3s from both server and worker nodes, and clean up all resources.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **SSH Configuration**: Creates a secure SSH configuration for connecting to nodes
|
||||||
|
- **K3s Server Installation**: Installs K3s on the server node with customizable options
|
||||||
|
- **Kubeconfig Management**: Retrieves and configures the kubeconfig for local access
|
||||||
|
- **Worker Node Deployment**: Joins worker nodes to the cluster using the node token
|
||||||
|
- **Clean Uninstallation**: Properly cleans up all components on terraform destroy
|
||||||
|
- **Flexible Configuration**: Supports both variable files and environment variables
|
||||||
|
|
||||||
|
## Customization Options
|
||||||
|
|
||||||
|
- **Traefik Dashboard**: Enable with `enable_traefik_dashboard = true`
|
||||||
|
- **SSL Configuration**: Enable with `enable_ssl = true` and provide certificate paths
|
||||||
|
- **Custom K3s Version**: Specify with `k3s_version` variable
|
||||||
|
- **Additional Arguments**: Pass extra arguments to both server and agent installs
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
If you encounter issues:
|
||||||
|
|
||||||
|
1. Check SSH connectivity to all nodes
|
||||||
|
2. Verify that the SSH user has sufficient permissions
|
||||||
|
3. Ensure all nodes meet the system requirements for K3s
|
||||||
|
4. Check the logs on each node at `/var/log/k3s.log` or `/var/log/k3s-agent.log`
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
- The SSH configuration disables strict host key checking for convenience but consider enabling it in production
|
||||||
|
- Secure your kubeconfig file as it contains authentication information
|
||||||
|
- Consider using an SSH agent or SSH certificates for improved security
|
||||||
34
terraform/infra/dev/env.tf
Normal file
34
terraform/infra/dev/env.tf
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# This file handles environment variable loading from .env file
|
||||||
|
|
||||||
|
locals {
|
||||||
|
# Parse .env file if it exists and make variables available
|
||||||
|
env_file_exists = fileexists("${path.module}/.env")
|
||||||
|
|
||||||
|
# Read and parse .env file content
|
||||||
|
env_file_content = local.env_file_exists ? file("${path.module}/.env") : ""
|
||||||
|
|
||||||
|
# Convert lines to key-value pairs
|
||||||
|
env_vars = local.env_file_exists ? {
|
||||||
|
for line in compact(split("\n", local.env_file_content)) :
|
||||||
|
trimspace(split("=", line)[0]) => trimspace(join("=", slice(split("=", line), 1, length(split("=", line)))))
|
||||||
|
if length(split("=", line)) > 1 && !startswith(trimspace(line), "#")
|
||||||
|
} : {}
|
||||||
|
|
||||||
|
# Environment variables that can override Terraform variables
|
||||||
|
server_ip_override = lookup(local.env_vars, "SERVER_IP", "")
|
||||||
|
worker_ips_override = lookup(local.env_vars, "WORKER_IPS", "")
|
||||||
|
ssh_user_override = lookup(local.env_vars, "SSH_USER", "")
|
||||||
|
ssh_private_key_override = lookup(local.env_vars, "SSH_PRIVATE_KEY", "")
|
||||||
|
domain_override = lookup(local.env_vars, "DOMAIN", "")
|
||||||
|
k3s_version_override = lookup(local.env_vars, "K3S_VERSION", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Use environment variables if provided, otherwise use terraform.tfvars values
|
||||||
|
locals {
|
||||||
|
effective_server_ip = local.server_ip_override != "" ? local.server_ip_override : var.server_ip
|
||||||
|
effective_worker_ips = local.worker_ips_override != "" ? split(",", local.worker_ips_override) : var.worker_ips
|
||||||
|
effective_ssh_user = local.ssh_user_override != "" ? local.ssh_user_override : var.ssh_user
|
||||||
|
effective_ssh_private_key = local.ssh_private_key_override != "" ? local.ssh_private_key_override : var.ssh_private_key
|
||||||
|
effective_domain = local.domain_override != "" ? local.domain_override : var.domain
|
||||||
|
effective_k3s_version = local.k3s_version_override != "" ? local.k3s_version_override : var.k3s_version
|
||||||
|
}
|
||||||
56
terraform/infra/dev/main.tf
Normal file
56
terraform/infra/dev/main.tf
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
locals {
|
||||||
|
# Load environment variables if .env file exists
|
||||||
|
env_vars = fileexists("${path.module}/.env") ? {
|
||||||
|
for line in [
|
||||||
|
for line in split("\n", file("${path.module}/.env"))
|
||||||
|
: line if length(regexall("^[A-Za-z][A-Za-z0-9_]*=.*$", line)) > 0
|
||||||
|
] : split("=", line)[0] => join("=", slice(split("=", line), 1, length(split("=", line))))
|
||||||
|
} : {}
|
||||||
|
}
|
||||||
|
|
||||||
|
module "k3s_cluster" {
|
||||||
|
source = "../../modules/k3s-install"
|
||||||
|
|
||||||
|
# Required parameters
|
||||||
|
server_ip = var.server_ip
|
||||||
|
worker_ips = var.worker_ips
|
||||||
|
ssh_user = var.ssh_user
|
||||||
|
ssh_private_key = var.ssh_private_key
|
||||||
|
replace_url = var.replace_url != "" ? var.replace_url : var.server_ip
|
||||||
|
|
||||||
|
# Optional parameters with defaults
|
||||||
|
k3s_version = var.k3s_version
|
||||||
|
k3s_channel = var.k3s_channel
|
||||||
|
kubeconfig_path = var.kubeconfig_path
|
||||||
|
node_token_path = var.node_token_path
|
||||||
|
|
||||||
|
# Conditional extra arguments
|
||||||
|
k3s_extra_server_args = join(" ", compact([
|
||||||
|
var.enable_traefik_dashboard ? "--set traefik.dashboard.enabled=true" : "",
|
||||||
|
var.enable_ssl ? "--tls-san=${var.domain}" : "",
|
||||||
|
var.k3s_extra_server_args
|
||||||
|
]))
|
||||||
|
|
||||||
|
k3s_extra_agent_args = var.k3s_extra_agent_args
|
||||||
|
}
|
||||||
|
|
||||||
|
# Output information about the deployed cluster
|
||||||
|
output "kubeconfig" {
|
||||||
|
description = "Path to the kubeconfig file"
|
||||||
|
value = module.k3s_cluster.kubeconfig_path
|
||||||
|
}
|
||||||
|
|
||||||
|
output "server_ip" {
|
||||||
|
description = "IP address of the K3s server"
|
||||||
|
value = module.k3s_cluster.server_ip
|
||||||
|
}
|
||||||
|
|
||||||
|
output "worker_ips" {
|
||||||
|
description = "IP addresses of K3s workers"
|
||||||
|
value = module.k3s_cluster.worker_ips
|
||||||
|
}
|
||||||
|
|
||||||
|
output "cluster_ready" {
|
||||||
|
description = "Indicator that the cluster is ready"
|
||||||
|
value = module.k3s_cluster.cluster_ready
|
||||||
|
}
|
||||||
17
terraform/infra/dev/providers.tf
Normal file
17
terraform/infra/dev/providers.tf
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
terraform {
|
||||||
|
required_version = ">= 1.0.0"
|
||||||
|
required_providers {
|
||||||
|
null = {
|
||||||
|
source = "hashicorp/null"
|
||||||
|
version = "~> 3.2.0"
|
||||||
|
}
|
||||||
|
local = {
|
||||||
|
source = "hashicorp/local"
|
||||||
|
version = "~> 2.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Provider configuration
|
||||||
|
provider "null" {}
|
||||||
|
provider "local" {}
|
||||||
28
terraform/infra/dev/terraform.tfvars
Normal file
28
terraform/infra/dev/terraform.tfvars
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# K3s Server Configuration
|
||||||
|
server_ip = "192.168.1.100" # Replace with your server IP
|
||||||
|
worker_ips = [ # Replace with your worker IPs
|
||||||
|
"192.168.1.101",
|
||||||
|
"192.168.1.102"
|
||||||
|
]
|
||||||
|
ssh_user = "ubuntu" # Replace with your SSH username
|
||||||
|
ssh_private_key = "~/.ssh/id_rsa" # Path to your private SSH key
|
||||||
|
replace_url = "" # Optional: URL to replace in kubeconfig, leave empty to use server_ip
|
||||||
|
|
||||||
|
# Cluster Configuration
|
||||||
|
domain = "reg.benadis.org" # Your domain name
|
||||||
|
k3s_version = "v1.27.3+k3s1" # K3s version to install
|
||||||
|
k3s_channel = "stable" # K3s release channel
|
||||||
|
kubeconfig_path = "~/.kube/config" # Where to save kubeconfig
|
||||||
|
node_token_path = "/tmp/node-token" # Where to save node token
|
||||||
|
|
||||||
|
# Optional Features
|
||||||
|
enable_traefik_dashboard = false # Enable Traefik dashboard
|
||||||
|
enable_ssl = false # Enable SSL
|
||||||
|
ssl_cert_path = "" # Path to SSL certificate
|
||||||
|
ssl_key_path = "" # Path to SSL key
|
||||||
|
install_argocd = false # Install ArgoCD
|
||||||
|
enable_ssh_tunnel = false # Enable SSH tunneling
|
||||||
|
|
||||||
|
# Advanced Configuration
|
||||||
|
k3s_extra_server_args = "" # Extra args for K3s server
|
||||||
|
k3s_extra_agent_args = "" # Extra args for K3s agent
|
||||||
105
terraform/infra/dev/variables.tf
Normal file
105
terraform/infra/dev/variables.tf
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
variable "server_ip" {
|
||||||
|
description = "IP address of the K3s server node"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "worker_ips" {
|
||||||
|
description = "List of IP addresses for K3s worker nodes"
|
||||||
|
type = list(string)
|
||||||
|
default = []
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_user" {
|
||||||
|
description = "SSH username for connecting to nodes"
|
||||||
|
type = string
|
||||||
|
default = "root"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_private_key" {
|
||||||
|
description = "Path to the SSH private key for authentication"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "replace_url" {
|
||||||
|
description = "URL to replace in the kubeconfig (usually the server_ip or domain name)"
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "domain" {
|
||||||
|
description = "Domain name for the cluster"
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "k3s_version" {
|
||||||
|
description = "Version of K3s to install"
|
||||||
|
type = string
|
||||||
|
default = "v1.27.3+k3s1"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "k3s_channel" {
|
||||||
|
description = "Release channel of K3s to install (stable, latest, etc.)"
|
||||||
|
type = string
|
||||||
|
default = "stable"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "kubeconfig_path" {
|
||||||
|
description = "Path where to save the kubeconfig file locally"
|
||||||
|
type = string
|
||||||
|
default = "~/.kube/config"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "node_token_path" {
|
||||||
|
description = "Path where to save the node token locally"
|
||||||
|
type = string
|
||||||
|
default = "/tmp/node-token"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "enable_traefik_dashboard" {
|
||||||
|
description = "Whether to enable the Traefik dashboard"
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "enable_ssl" {
|
||||||
|
description = "Whether to configure SSL for the cluster"
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssl_cert_path" {
|
||||||
|
description = "Path to SSL certificate"
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssl_key_path" {
|
||||||
|
description = "Path to SSL key"
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "install_argocd" {
|
||||||
|
description = "Whether to install ArgoCD for GitOps"
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "enable_ssh_tunnel" {
|
||||||
|
description = "Whether to enable SSH tunneling for local access"
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "k3s_extra_server_args" {
|
||||||
|
description = "Additional arguments to pass to the K3s server installation"
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "k3s_extra_agent_args" {
|
||||||
|
description = "Additional arguments to pass to the K3s agent installation"
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
270
terraform/modules/k3s-install/main.tf
Normal file
270
terraform/modules/k3s-install/main.tf
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
terraform {
|
||||||
|
required_version = ">= 1.0.0"
|
||||||
|
required_providers {
|
||||||
|
null = {
|
||||||
|
source = "hashicorp/null"
|
||||||
|
version = "~> 3.2.0"
|
||||||
|
}
|
||||||
|
local = {
|
||||||
|
source = "hashicorp/local"
|
||||||
|
version = "~> 2.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
locals {
|
||||||
|
ssh_config_path = "${path.module}/ssh_config"
|
||||||
|
temporary_dir = "/tmp/k3s-terraform"
|
||||||
|
server_kubeconfig = "${local.temporary_dir}/k3s.yaml"
|
||||||
|
node_token_path = "${local.temporary_dir}/node-token"
|
||||||
|
worker_count = length(var.worker_ips)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a temporary SSH config file for secure connections
|
||||||
|
resource "null_resource" "setup_ssh_config" {
|
||||||
|
triggers = {
|
||||||
|
server_ip = var.server_ip
|
||||||
|
worker_ips = join(",", var.worker_ips)
|
||||||
|
ssh_user = var.ssh_user
|
||||||
|
ssh_private_key = var.ssh_private_key
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "local-exec" {
|
||||||
|
command = <<-EOT
|
||||||
|
mkdir -p ${dirname(local.ssh_config_path)}
|
||||||
|
cat > ${local.ssh_config_path} << 'EOF'
|
||||||
|
Host ${var.server_ip}
|
||||||
|
User ${var.ssh_user}
|
||||||
|
IdentityFile ${var.ssh_private_key}
|
||||||
|
StrictHostKeyChecking no
|
||||||
|
UserKnownHostsFile /dev/null
|
||||||
|
|
||||||
|
${join("\n", [
|
||||||
|
for ip in var.worker_ips : <<-WORKER
|
||||||
|
Host ${ip}
|
||||||
|
User ${var.ssh_user}
|
||||||
|
IdentityFile ${var.ssh_private_key}
|
||||||
|
StrictHostKeyChecking no
|
||||||
|
UserKnownHostsFile /dev/null
|
||||||
|
WORKER
|
||||||
|
])}
|
||||||
|
EOF
|
||||||
|
EOT
|
||||||
|
interpreter = ["bash", "-c"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clean up SSH config on destroy
|
||||||
|
provisioner "local-exec" {
|
||||||
|
when = destroy
|
||||||
|
command = "rm -f ${self.triggers.ssh_config_path}"
|
||||||
|
interpreter = ["bash", "-c"]
|
||||||
|
on_failure = continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install K3s on the server node
|
||||||
|
resource "null_resource" "install_k3s_server" {
|
||||||
|
depends_on = [null_resource.setup_ssh_config]
|
||||||
|
|
||||||
|
triggers = {
|
||||||
|
server_ip = var.server_ip
|
||||||
|
ssh_user = var.ssh_user
|
||||||
|
ssh_private_key = var.ssh_private_key
|
||||||
|
ssh_config_path = local.ssh_config_path
|
||||||
|
k3s_version = var.k3s_version
|
||||||
|
k3s_extra_args = var.k3s_extra_server_args
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install K3s server
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
connection {
|
||||||
|
host = var.server_ip
|
||||||
|
user = var.ssh_user
|
||||||
|
private_key = file(var.ssh_private_key)
|
||||||
|
agent = false
|
||||||
|
}
|
||||||
|
|
||||||
|
inline = [
|
||||||
|
"mkdir -p ${local.temporary_dir}",
|
||||||
|
"curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=${var.k3s_version} INSTALL_K3S_CHANNEL=${var.k3s_channel} sh -s - server ${var.k3s_extra_server_args}",
|
||||||
|
"until systemctl is-active --quiet k3s; do echo 'Waiting for k3s to start...'; sleep 5; done",
|
||||||
|
"echo 'K3s server installation complete'"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Uninstall K3s server on destroy
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
when = destroy
|
||||||
|
connection {
|
||||||
|
host = self.triggers.server_ip
|
||||||
|
user = self.triggers.ssh_user
|
||||||
|
private_key = file(self.triggers.ssh_private_key)
|
||||||
|
agent = false
|
||||||
|
}
|
||||||
|
|
||||||
|
inline = [
|
||||||
|
"/usr/local/bin/k3s-uninstall.sh || true",
|
||||||
|
"rm -rf ${local.temporary_dir} || true"
|
||||||
|
]
|
||||||
|
on_failure = continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Retrieve the K3s kubeconfig from the server
|
||||||
|
resource "null_resource" "get_k3s_config" {
|
||||||
|
depends_on = [null_resource.install_k3s_server, null_resource.setup_ssh_config]
|
||||||
|
|
||||||
|
triggers = {
|
||||||
|
server_ip = var.server_ip
|
||||||
|
ssh_user = var.ssh_user
|
||||||
|
ssh_private_key = var.ssh_private_key
|
||||||
|
ssh_config_path = local.ssh_config_path
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy kubeconfig to a temporary location on server
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
connection {
|
||||||
|
host = var.server_ip
|
||||||
|
user = var.ssh_user
|
||||||
|
private_key = file(var.ssh_private_key)
|
||||||
|
agent = false
|
||||||
|
}
|
||||||
|
|
||||||
|
inline = [
|
||||||
|
"mkdir -p ${local.temporary_dir}",
|
||||||
|
"sudo cp /etc/rancher/k3s/k3s.yaml ${local.server_kubeconfig}",
|
||||||
|
"sudo chmod 644 ${local.server_kubeconfig}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download kubeconfig to local machine
|
||||||
|
provisioner "local-exec" {
|
||||||
|
command = "mkdir -p ${dirname(var.kubeconfig_path)} && scp -F ${local.ssh_config_path} ${var.ssh_user}@${var.server_ip}:${local.server_kubeconfig} ${var.kubeconfig_path}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update server URL in kubeconfig if needed
|
||||||
|
provisioner "local-exec" {
|
||||||
|
command = <<-EOT
|
||||||
|
if [ -n "${var.replace_url}" ]; then
|
||||||
|
sed -i 's|https://127.0.0.1:6443|https://${var.replace_url}:6443|g' ${var.kubeconfig_path}
|
||||||
|
fi
|
||||||
|
EOT
|
||||||
|
interpreter = ["bash", "-c"]
|
||||||
|
on_failure = continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Retrieve the K3s node token from the server
|
||||||
|
resource "null_resource" "get_k3s_token" {
|
||||||
|
depends_on = [null_resource.install_k3s_server, null_resource.setup_ssh_config]
|
||||||
|
|
||||||
|
triggers = {
|
||||||
|
server_ip = var.server_ip
|
||||||
|
ssh_user = var.ssh_user
|
||||||
|
ssh_private_key = var.ssh_private_key
|
||||||
|
ssh_config_path = local.ssh_config_path
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extract node token and save to a temporary file
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
connection {
|
||||||
|
host = var.server_ip
|
||||||
|
user = var.ssh_user
|
||||||
|
private_key = file(var.ssh_private_key)
|
||||||
|
agent = false
|
||||||
|
}
|
||||||
|
|
||||||
|
inline = [
|
||||||
|
"mkdir -p ${local.temporary_dir}",
|
||||||
|
"sudo cat /var/lib/rancher/k3s/server/node-token > ${local.node_token_path}",
|
||||||
|
"sudo chmod 644 ${local.node_token_path}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download node token to local machine
|
||||||
|
provisioner "local-exec" {
|
||||||
|
command = "mkdir -p ${dirname(var.node_token_path)} && scp -F ${local.ssh_config_path} ${var.ssh_user}@${var.server_ip}:${local.node_token_path} ${var.node_token_path}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Copy the node token to each worker node
|
||||||
|
resource "null_resource" "copy_token_to_workers" {
|
||||||
|
depends_on = [null_resource.get_k3s_token]
|
||||||
|
count = local.worker_count
|
||||||
|
|
||||||
|
triggers = {
|
||||||
|
worker_ip = var.worker_ips[count.index]
|
||||||
|
ssh_user = var.ssh_user
|
||||||
|
ssh_private_key = var.ssh_private_key
|
||||||
|
ssh_config_path = local.ssh_config_path
|
||||||
|
node_token_path = var.node_token_path
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create temporary directory on worker and copy token
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
connection {
|
||||||
|
host = var.worker_ips[count.index]
|
||||||
|
user = var.ssh_user
|
||||||
|
private_key = file(var.ssh_private_key)
|
||||||
|
agent = false
|
||||||
|
}
|
||||||
|
|
||||||
|
inline = [
|
||||||
|
"mkdir -p ${local.temporary_dir}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Upload token file to worker
|
||||||
|
provisioner "local-exec" {
|
||||||
|
command = "scp -F ${local.ssh_config_path} ${var.node_token_path} ${var.ssh_user}@${var.worker_ips[count.index]}:${local.node_token_path}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install K3s on each worker node
|
||||||
|
resource "null_resource" "install_k3s_worker" {
|
||||||
|
depends_on = [null_resource.copy_token_to_workers]
|
||||||
|
count = local.worker_count
|
||||||
|
|
||||||
|
triggers = {
|
||||||
|
worker_ip = var.worker_ips[count.index]
|
||||||
|
server_ip = var.server_ip
|
||||||
|
ssh_user = var.ssh_user
|
||||||
|
ssh_private_key = var.ssh_private_key
|
||||||
|
ssh_config_path = local.ssh_config_path
|
||||||
|
k3s_version = var.k3s_version
|
||||||
|
k3s_extra_args = var.k3s_extra_agent_args
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install K3s agent on worker
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
connection {
|
||||||
|
host = var.worker_ips[count.index]
|
||||||
|
user = var.ssh_user
|
||||||
|
private_key = file(var.ssh_private_key)
|
||||||
|
agent = false
|
||||||
|
}
|
||||||
|
|
||||||
|
inline = [
|
||||||
|
"curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=${var.k3s_version} INSTALL_K3S_CHANNEL=${var.k3s_channel} K3S_URL=https://${var.server_ip}:6443 K3S_TOKEN=$(cat ${local.node_token_path}) sh -s - agent ${var.k3s_extra_agent_args}",
|
||||||
|
"until systemctl is-active --quiet k3s-agent; do echo 'Waiting for k3s-agent to start...'; sleep 5; done",
|
||||||
|
"echo 'K3s agent installation complete'"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Uninstall K3s agent on destroy
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
when = destroy
|
||||||
|
connection {
|
||||||
|
host = self.triggers.worker_ip
|
||||||
|
user = self.triggers.ssh_user
|
||||||
|
private_key = file(self.triggers.ssh_private_key)
|
||||||
|
agent = false
|
||||||
|
}
|
||||||
|
|
||||||
|
inline = [
|
||||||
|
"/usr/local/bin/k3s-agent-uninstall.sh || true",
|
||||||
|
"rm -rf ${local.temporary_dir} || true"
|
||||||
|
]
|
||||||
|
on_failure = continue
|
||||||
|
}
|
||||||
|
}
|
||||||
24
terraform/modules/k3s-install/outputs.tf
Normal file
24
terraform/modules/k3s-install/outputs.tf
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
output "kubeconfig_path" {
|
||||||
|
description = "Path to the kubeconfig file"
|
||||||
|
value = var.kubeconfig_path
|
||||||
|
}
|
||||||
|
|
||||||
|
output "server_ip" {
|
||||||
|
description = "IP address of the K3s server node"
|
||||||
|
value = var.server_ip
|
||||||
|
}
|
||||||
|
|
||||||
|
output "worker_ips" {
|
||||||
|
description = "IP addresses of the K3s worker nodes"
|
||||||
|
value = var.worker_ips
|
||||||
|
}
|
||||||
|
|
||||||
|
output "cluster_ready" {
|
||||||
|
description = "Indicator that the cluster is ready to use"
|
||||||
|
value = "true"
|
||||||
|
depends_on = [
|
||||||
|
null_resource.install_k3s_server,
|
||||||
|
null_resource.get_k3s_config,
|
||||||
|
null_resource.install_k3s_worker
|
||||||
|
]
|
||||||
|
}
|
||||||
69
terraform/modules/k3s-install/variables.tf
Normal file
69
terraform/modules/k3s-install/variables.tf
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
variable "server_ip" {
|
||||||
|
description = "IP address of the K3s server node"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "worker_ips" {
|
||||||
|
description = "List of IP addresses of the K3s worker nodes"
|
||||||
|
type = list(string)
|
||||||
|
default = []
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_user" {
|
||||||
|
description = "SSH username for connecting to nodes"
|
||||||
|
type = string
|
||||||
|
default = "root"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_private_key" {
|
||||||
|
description = "Path to the SSH private key for authentication"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "replace_url" {
|
||||||
|
description = "URL to replace in the kubeconfig (usually the server_ip or domain name)"
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "k3s_version" {
|
||||||
|
description = "Version of K3s to install"
|
||||||
|
type = string
|
||||||
|
default = "v1.27.3+k3s1"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "k3s_channel" {
|
||||||
|
description = "Release channel of K3s to install (stable, latest, etc.)"
|
||||||
|
type = string
|
||||||
|
default = "stable"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "k3s_extra_server_args" {
|
||||||
|
description = "Extra arguments to pass to the K3s server"
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "k3s_extra_agent_args" {
|
||||||
|
description = "Extra arguments to pass to the K3s agent"
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "kubeconfig_path" {
|
||||||
|
description = "Path where to save the kubeconfig file locally"
|
||||||
|
type = string
|
||||||
|
default = "~/.kube/config"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_key_algorithm" {
|
||||||
|
description = "SSH key algorithm used"
|
||||||
|
type = string
|
||||||
|
default = "rsa"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "node_token_path" {
|
||||||
|
description = "Path where to save the node token locally"
|
||||||
|
type = string
|
||||||
|
default = "/tmp/node-token"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user