用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/diegosouzapw/awesome-omni-skill --skill opentofu-kubernetes-explorer命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Token-efficient tracking for AI orchestration. CLI-first for status updates (~50 tokens), agent fallback for complex ops (~1KB). Use when: updating task status, querying blockers, creating progress files, validating phases.
AshAi extension guidelines for integrating AI capabilities with Ash Framework. Use when implementing vectorization/embeddings, exposing Ash actions as LLM tools, creating prompt-backed actions, or setting up MCP servers. Covers semantic search, LangChain integration, and structured outputs.
This skill should be used when solving hard questions, complex architectural problems, or debugging issues that benefit from GPT-5 Pro or GPT-5.1 thinking models with large file context. Use when standard Claude analysis needs deeper reasoning or extended context windows.
基于 SOC 职业分类
正在显示 SKILL.md
| name | opentofu-kubernetes-explorer |
| description | Explore and manage Kubernetes clusters and resources using OpenTofu/Terraform |
| license | Apache-2.0 |
| compatibility | opencode |
| metadata | {"audience":"developers","workflow":"container-orchestration"} |
I guide you through managing Kubernetes clusters and resources using Kubernetes provider for OpenTofu/Terraform. I help you:
Use this skill when you need to:
Note: OpenTofu and Terraform are used interchangeably throughout this skill. OpenTofu is an open-source implementation of Terraform and maintains full compatibility with Terraform providers.
# Verify OpenTofu installation
tofu version
# Initialize project
mkdir kubernetes-terraform
cd kubernetes-terraform
tofu init
Create versions.tf:
terraform {
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.24.0"
}
helm = {
source = "hashicorp/helm"
version = "~> 2.11.0"
}
}
required_version = ">= 1.0"
# Remote state backend
backend "s3" {
bucket = "terraform-state"
key = "kubernetes/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
Create provider.tf:
provider "kubernetes" {
# Method 1: Use default kubeconfig (recommended)
# Uses ~/.kube/config by default
# Best for local development and single cluster
# Method 2: Specify kubeconfig path
config_path = var.kubeconfig_path
# Method 3: Use config context
config_context = "my-cluster-context"
# Method 4: Direct cluster configuration (for EKS)
host = data.aws_eks_cluster.cluster.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
token = data.aws_eks_cluster_auth.cluster.token
# Namespace configuration
config_context_auth_info = false
}
provider "helm" {
kubernetes {
config_path = var.kubeconfig_path
}
}
# Method 1: Use default kubeconfig
# Provider automatically uses ~/.kube/config
# Method 2: Specify kubeconfig path
export KUBECONFIG="/path/to/kubeconfig"
# Method 3: Use config context
export KUBECONFIG="/path/to/kubeconfig"
kubectl config use-context my-cluster-context
# Method 4: For EKS with AWS credentials
# Set AWS environment variables
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_DEFAULT_REGION="ap-southeast-1"
Create namespace.tf:
# Application namespace
resource "kubernetes_namespace" "app" {
metadata {
name = var.app_namespace
labels = {
app = var.application_name
managedBy = "terraform"
environment = var.environment
}
}
}
# Monitoring namespace
resource "kubernetes_namespace" "monitoring" {
metadata {
name = "monitoring"
labels = {
name = "monitoring"
managedBy = "terraform"
}
}
}
# Ingress namespace
resource "kubernetes_namespace" "ingress" {
metadata {
name = "ingress-nginx"
labels = {
app = "ingress-nginx"
managedBy = "terraform"
}
}
}
Create config.tf:
# Application ConfigMap
resource "kubernetes_config_map" "app_config" {
metadata {
name = "app-config"
namespace = kubernetes_namespace.app.metadata[0].name
}
data = {
"application.properties" = <<-EOT
server.port=8080
database.url=${var.database_url}
logging.level=INFO
environment=${var.environment}
EOT
"logback.xml" = file("${path.module}/config/logback.xml")
}
}
# Application Secret
resource "kubernetes_secret" "app_secret" {
metadata {
name = "app-secret"
namespace = kubernetes_namespace.app.metadata[0].name
}
data = {
"database-password" = var.database_password
"api-key" = var.api_key
}
type = "Opaque"
}
Create deployment.tf:
# Application Deployment
resource "kubernetes_deployment" "app" {
metadata {
name = var.application_name
namespace = kubernetes_namespace.app.metadata[0].name
labels = {
app = var.application_name
}
}
spec {
replicas = var.replicas
selector {
match_labels = {
app = var.application_name
}
}
template {
metadata {
labels = {
app = var.application_name
}
}
spec {
container {
name = "app"
image = var.container_image
port {
container_port = 8080
}
# Environment variables
env {
name = "SERVER_PORT"
value = "8080"
}
env {
name = "DATABASE_URL"
value_from {
secret_key_ref {
name = kubernetes_secret.app_secret.metadata[0].name
key = "database-password"
}
}
}
# Resource limits
resources {
limits = {
cpu = "500m"
memory = "512Mi"
}
requests = {
cpu = "250m"
memory = "256Mi"
}
}
# Liveness probe
liveness_probe {
http_get {
path = "/health"
port = 8080
}
initial_delay_seconds = 10
period_seconds = 10
timeout_seconds = 5
failure_threshold = 3
}
# Readiness probe
readiness_probe {
http_get {
path = "/ready"
port = 8080
}
initial_delay_seconds = 5
period_seconds = 5
timeout_seconds = 3
failure_threshold = 2
}
}
}
}
}
# Prevent pod disruption during update
strategy {
type = "RollingUpdate"
rolling_update {
max_surge = 1
max_unavailable = 0
}
}
}
Create service.tf:
# Application Service (ClusterIP)
resource "kubernetes_service" "app" {
metadata {
name = var.application_name
namespace = kubernetes_namespace.app.metadata[0].name
labels = {
app = var.application_name
}
}
spec {
type = "ClusterIP"
selector {
app = var.application_name
}
port {
name = "http"
protocol = "TCP"
port = 80
target_port = 8080
}
}
}
# Application Service (LoadBalancer)
resource "kubernetes_service" "app_lb" {
metadata {
name = "${var.application_name}-lb"
namespace = kubernetes_namespace.app.metadata[0].name
labels = {
app = var.application_name
}
annotations = {
"service.beta.kubernetes.io/aws-load-balancer-type" = "nlb"
}
}
spec {
type = "LoadBalancer"
selector {
app = var.application_name
}
port {
name = "http"
protocol = "TCP"
port = 80
target_port = 8080
}
port {
name = "https"
protocol = "TCP"
port = 443
target_port = 8080
}
}
}
# Headless Service for StatefulSets
resource "kubernetes_service" "app_headless" {
metadata {
name = "${var.application_name}-headless"
namespace = kubernetes_namespace.app.metadata[0].name
labels = {
app = var.application_name
}
}
spec {
type = "ClusterIP"
cluster_ip = "None"
selector {
app = var.application_name
}
port {
name = "http"
protocol = "TCP"
port = 8080
target_port = 8080
}
}
}
Create ingress.tf:
# Ingress Controller Deployment (nginx)
resource "helm_release" "ingress_nginx" {
name = "ingress-nginx"
repository = "https://kubernetes.github.io/ingress-nginx"
chart = "ingress-nginx"
namespace = kubernetes_namespace.ingress.metadata[0].name
set {
name = "controller.service.type"
value = "LoadBalancer"
}
set {
name = "controller.publishService.enabled"
value = "true"
}
}
# Application Ingress
resource "kubernetes_ingress" "app" {
metadata {
name = var.application_name
namespace = kubernetes_namespace.app.metadata[0].name
labels = {
app = var.application_name
}
annotations = {
"kubernetes.io/ingress.class" = "nginx"
"cert-manager.io/cluster-issuer" = "letsencrypt-prod"
"nginx.ingress.kubernetes.io/ssl-redirect" = "true"
}
}
spec {
rule {
host = var.ingress_host
http {
path {
backend {
service_name = kubernetes_service.app.metadata[0].name
service_port = 80
}
path = "/"
}
}
}
tls {
hosts = [var.ingress_host]
secret_name = kubernetes_secret.tls_cert.metadata[0].name
}
}
}
Create storage.tf:
# Storage Class
resource "kubernetes_storage_class" "gp2" {
metadata {
name = "gp2"
}
storage_provisioner = "kubernetes.io/aws-ebs"
parameters = {
type = "gp2"
}
allow_volume_expansion = true
reclaim_policy = "Retain"
volume_binding_mode = "WaitForFirstConsumer"
}
# Persistent Volume Claim
resource "kubernetes_persistent_volume_claim" "data" {
metadata {
name = "app-data"
namespace = kubernetes_namespace.app.metadata[0].name
}
spec {
access_modes = ["ReadWriteOnce"]
storage_class_name = kubernetes_storage_class.gp2.metadata[0].name
resources {
requests = {
storage = "10Gi"
}
}
}
}
Create helm.tf:
# Redis Deployment
resource "helm_release" "redis" {
name = "redis"
repository = "https://charts.bitnami.com/bitnami"
chart = "redis"
namespace = kubernetes_namespace.app.metadata[0].name
version = "17.11.0"
set {
name = "auth.enabled"
value = "true"
}
set {
name = "auth.password"
value = var.redis_password
}
set {
name = "persistence.enabled"
value = "true"
}
set {
name = "persistence.size"
value = "8Gi"
}
}
# PostgreSQL Deployment
resource "helm_release" "postgresql" {
name = "postgresql"
repository = "https://charts.bitnami.com/bitnami"
chart = "postgresql"
namespace = kubernetes_namespace.app.metadata[0].name
version = "12.5.0"
set {
name = "auth.enablePostgresUser"
value = "true"
}
set {
name = "auth.password"
value = var.postgresql_password
}
set {
name = "auth.database"
value = "appdb"
}
set {
name = "primary.persistence.enabled"
value = "true"
}
set {
name = "primary.persistence.size"
value = "20Gi"
}
}
Create autoscaler.tf:
resource "kubernetes_horizontal_pod_autoscaler" "app" {
metadata {
name = "${var.application_name}-hpa"
namespace = kubernetes_namespace.app.metadata[0].name
}
spec {
scale_target_ref {
api_version = "apps/v1"
kind = "Deployment"
name = kubernetes_deployment.app.metadata[0].name
}
min_replicas = var.min_replicas
max_replicas = var.max_replicas
target_cpu_utilization_percentage = 60
target_memory_utilization_percentage = 70
}
}
Create variables.tf:
variable "kubeconfig_path" {
description = "Path to kubeconfig file"
type = string
default = "~/.kube/config"
}
variable "app_namespace" {
description = "Application namespace"
type = string
default = "app"
}
variable "application_name" {
description = "Application name"
type = string
}
variable "container_image" {
description = "Container image to deploy"
type = string
}
variable "replicas" {
description = "Number of replicas"
type = number
default = 3
}
variable "min_replicas" {
description = "Minimum replicas for autoscaling"
type = number
default = 2
}
variable "max_replicas" {
description = "Maximum replicas for autoscaling"
type = number
default = 10
}
variable "database_url" {
description = "Database connection URL"
type = string
sensitive = true
}
variable "database_password" {
description = "Database password"
type = string
sensitive = true
}
variable "api_key" {
description = "API key"
type = string
sensitive = true
}
variable "ingress_host" {
description = "Ingress host"
type = string
}
variable "redis_password" {
description = "Redis password"
type = string
sensitive = true
}
variable "postgresql_password" {
description = "PostgreSQL password"
type = string
sensitive = true
}
variable "environment" {
description = "Environment name"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
Create outputs.tf:
output "namespace" {
description = "Application namespace"
value = kubernetes_namespace.app.metadata[0].name
}
output "deployment_name" {
description = "Application deployment name"
value = kubernetes_deployment.app.metadata[0].name
}
output "service_name" {
description = "Application service name"
value = kubernetes_service.app.metadata[0].name
}
output "load_balancer_url" {
description = "Load balancer URL"
value = kubernetes_service.app_lb.status[0].load_balancer[0].ingress[0].hostname
}
output "ingress_url" {
description = "Ingress URL"
value = "https://${var.ingress_host}"
}
# Set kubeconfig
export KUBECONFIG="/path/to/kubeconfig"
# Initialize providers
tofu init
# Plan changes
tofu plan -out=tfplan
# Apply changes
tofu apply tfplan
# Show outputs
tofu output
# Verify deployment
kubectl get all -n $APP_NAMESPACE
kubectl logs -f deployment/app -n $APP_NAMESPACE
set blocks to override default valuesSymptom: Error Error: Failed to configure provider
Solution:
# Verify kubeconfig
kubectl cluster-info
kubectl config current-context
# Check kubeconfig path
ls -la ~/.kube/config
# Test connection
kubectl get nodes
# Verify KUBECONFIG environment variable
echo $KUBECONFIG
# For EKS with AWS credentials
aws eks describe-cluster --name my-cluster --region ap-southeast-1
Symptom: Error Failed to pull image
Solution:
# Verify image exists
docker pull <image-name>
# Check image registry access
docker login <registry-url>
# Use image pull secrets
kubectl create secret docker-registry regcred \
--docker-server=<registry-url> \
--docker-username=<username> \
--docker-password=<password>
# Reference: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
Symptom: Pods stuck in Pending state
Solution:
# Describe pod for details
kubectl describe pod <pod-name>
# Check events
kubectl get events --sort-by='.lastTimestamp'
# Common issues:
# - Insufficient resources (check requests/limits)
# - Node affinity (check node selectors)
# - Taints and tolerations
# - Image pull errors
Symptom: Service is created but not accessible
Solution:
# Check service endpoints
kubectl get endpoints <service-name>
# Verify pod labels match service selector
kubectl get pods --show-labels
# Check service type
# ClusterIP: Only accessible within cluster
# LoadBalancer: External access via LB DNS/URL
# NodePort: External access via NodeIP:Port
# For LoadBalancer, check firewall/security groups
# Allow traffic to LB ports
Symptom: Ingress created but traffic not reaching pods
Solution:
# Verify ingress controller is running
kubectl get pods -n ingress-nginx
# Check ingress class annotation
kubectl describe ingress <ingress-name>
# Verify TLS secret exists
kubectl get secret <tls-secret-name>
# Check ingress backend service
kubectl get svc <backend-service-name>
# Check DNS resolution
nslookup <ingress-host>
dig <ingress-host>
# Reference: https://kubernetes.io/docs/concepts/services-networking/ingress/
Symptom: Pod fails with volume mount errors
Solution:
# Check PVC status
kubectl get pvc
# Check storage class
kubectl get sc
# Verify volume exists
kubectl get pv
# Check pod events
kubectl describe pod <pod-name> | grep -A 10 Events
# Ensure storage class supports dynamic provisioning
# Check reclaim_policy and volume_binding_mode
Symptom: Error Error: failed to upgrade release
Solution:
# Check Helm release history
helm list -n <namespace>
# Get current values
helm get values <release-name> -n <namespace>
# Dry-run upgrade
helm upgrade --dry-run <release-name> <chart> -n <namespace>
# Rollback if needed
helm rollback <release-name> <revision> -n <namespace>
# Check chart compatibility
# Ensure chart version supports Kubernetes version
kubectl version
helm search repo <chart-name> --versions
Symptom: HPA not scaling pods
Solution:
# Check HPA status
kubectl get hpa
# Describe HPA for details
kubectl describe hpa <hpa-name>
# Check resource requests (required for HPA)
kubectl describe pod <pod-name> | grep -A 5 Requests
# Verify metrics server is running
kubectl get pods -n kube-system | grep metrics
# Check metrics availability
kubectl top nodes
kubectl top pods
# namespace.tf
resource "kubernetes_namespace" "app" {
metadata {
name = "production"
}
}
# config.tf
resource "kubernetes_config_map" "app_config" {
metadata {
name = "app-config"
namespace = kubernetes_namespace.app.metadata[0].name
}
data = {
"config.json" = jsonencode({
port = 8080
env = "production"
})
}
}
# deployment.tf
resource "kubernetes_deployment" "app" {
metadata {
name = "webapp"
namespace = kubernetes_namespace.app.metadata[0].name
}
spec {
replicas = 3
template {
spec {
container {
name = "webapp"
image = "nginx:1.21"
port {
container_port = 80
}
resources {
limits = {
cpu = "500m"
memory = "512Mi"
}
requests = {
cpu = "250m"
memory = "256Mi"
}
}
}
}
}
}
}
# ingress.tf
resource "kubernetes_ingress" "app" {
metadata {
name = "webapp-ingress"
namespace = kubernetes_namespace.app.metadata[0].name
annotations = {
"kubernetes.io/ingress.class" = "nginx"
"cert-manager.io/cluster-issuer" = "letsencrypt-prod"
}
}
spec {
rule {
host = "app.example.com"
http {
path {
backend {
service_name = kubernetes_service.webapp.metadata[0].name
service_port = 80
}
}
}
}
tls {
hosts = ["app.example.com"]
secret_name = kubernetes_secret.tls_cert.metadata[0].name
}
}
}
# helm.tf
resource "helm_release" "redis" {
name = "redis"
repository = "https://charts.bitnami.com/bitnami"
chart = "redis"
namespace = kubernetes_namespace.app.metadata[0].name
set {
name = "auth.enabled"
value = "true"
}
set {
name = "auth.password"
value = var.redis_password
}
set {
name = "master.persistence.size"
value = "8Gi"
}
}
# eks.tf
resource "aws_eks_cluster" "main" {
name = "my-eks-cluster"
role_arn = aws_iam_role.eks_cluster.arn
version = "1.27"
vpc_config {
subnet_ids = aws_subnet.public[*].id
}
}
data "aws_eks_cluster" "cluster" {
name = aws_eks_cluster.main.name
}
data "aws_eks_cluster_auth" "cluster" {
name = aws_eks_cluster.main.name
}
# kubernetes.tf
provider "kubernetes" {
host = data.aws_eks_cluster.cluster.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority[0].data)
token = data.aws_eks_cluster_auth.cluster.token
}
resource "kubernetes_deployment" "app" {
metadata {
name = "app"
namespace = kubernetes_namespace.app.metadata[0].name
}
spec {
template {
spec {
container {
name = "app"
image = "my-app:latest"
}
}
}
}
}
helm upgrade --dry-run to test changeskubectl port-forward for local debuggingkubectl logs -f for real-time debuggingkubectl describe for detailed resource informationhelm show values to understand default configurationAfter mastering Kubernetes provider, explore: