Talos에서 Cilium을 커스텀 CNI로 사용하고자 할 때, Helm 차트를 Terraform으로 배포하는 도중에 kube-proxy 역할을 넘겨받고, 경우에 따라 kubeadm 인증서를 갱신하기도 하기 때문에 발생하는 것 같은데… 이 과정에서 Terraform은 Helm 배포가 완료되기를 기다리는 반면, kubectl은 일시적으로 작동하지 않더라구요. Helm 차트는 정상적으로 설치된 것처럼 보이지만, helm list 명령어로는 확인할 수 없는 일종의 ‘ghost install’ 상태가 되고, Terraform은 에러를 반환합니다.
│ Error: installation failed
│
│ with helm_release.cilium,
│ on helm.tf line 15, in resource "helm_release" "cilium":
│ 15: resource "helm_release" "cilium" {
│
│ cannot re-use a name that is still in use
Talos 클러스터는 부트스트랩 직후 CNI가 없는 상태에서 시작되고, 이 시점에 Helm을 이용해 Cilium을 설치하려 하면 네트워크 자체가 아직 구성되지 않았기 때문에 문제가 발생하네요.
추가적으로, Talos는 기본적으로 kube-proxy를 사용하지 않으며, Cilium이 그 역할을 대체하려다 보니 설치 시점에서 클러스터 내부 통신이 잠시 중단되고 kubectl 명령도 실패하게 됩니다. 그 결과, Helm은 release 정보를 제대로 생성하지 못하고, Cilium은 설치된 것처럼 보이지만 helm list에는 나타나지 않는 상태가 되는 것입니다.
resource "null_resource" "wait" {
depends_on = [local_file.kubeconfig, talos_machine_bootstrap.control_node]
triggers = {
kubeconfig_content = local_file.kubeconfig.content
}
provisioner "local-exec" {
environment = {
KUBECONFIG = "${var.config_output_path}/kubeconfig"
}
command = "${path.module}/scripts/wait-for-cluster-ready.bash"
}
}
resource "helm_release" "cilium" {
depends_on = [null_resource.wait]
name = "cilium"
repository = "https://helm.cilium.io/"
chart = "cilium"
version = "1.17.5"
namespace = "kube-system"
create_namespace = false
# Avoid a race condition issue where helm provider errors with;
# "cannot re-use a name that is still in use"
atomic = true
timeout = 500
# Contact the kubeapi by using a Talos VIP to avoid the chicken&egg problem
# of trying to replace kube-proxy with no CNI installed.
set = [
{
name = "kubeProxyReplacement"
value = true
},
{
name = "k8sServiceHost"
value = var.cluster_endpoint_domain
},
{
name = "k8sServicePort"
value = 6443
},
{
name = "securityContext.capabilities.ciliumAgent"
value = "{CHOWN,KILL,NET_ADMIN,NET_RAW,IPC_LOCK,SYS_ADMIN,SYS_RESOURCE,DAC_OVERRIDE,FOWNER,SETGID,SETUID}"
},
{
name = "securityContext.capabilities.cleanCiliumState"
value = "{NET_ADMIN,SYS_ADMIN,SYS_RESOURCE}"
}
]
}
resource "kubernetes_namespace" "ceph_csi_cephfs" {
# This is only for the reverse dependency graph created on destroy.
# To avoid the API going down before this namespace is deleted.
depends_on = [talos_machine_bootstrap.control_node]
metadata {
labels = {
"pod-security.kubernetes.io/enforce" = "privileged"
}
name = "ceph-csi-cephfs"
}
}
resource "helm_release" "cephfs_csi" {
depends_on = [
null_resource.wait,
kubernetes_namespace.ceph_csi_cephfs,
helm_release.cilium
]
name = "ceph-csi-cephfs"
repository = "https://ceph.github.io/csi-charts"
chart = "ceph-csi-cephfs"
version = "3.14.0"
namespace = "ceph-csi-cephfs"
create_namespace = false
# Avoid a race condition issue where helm provider errors with;
# "cannot re-use a name that is still in use"
atomic = true
timeout = 500
# Set value overrides.
set = [
{
name = "secret.create"
value = true
},
{
name = "secret.userID"
value = var.cephfs_csi.userid
},
{
name = "secret.userKey"
value = var.cephfs_csi.userkey
},
{
name = "storageClass.clusterID"
value = var.cephfs_csi.clusterid
},
{
name = "storageClass.create"
value = true
},
{
name = "storageClass.fsName"
value = var.cephfs_csi.fsname
},
{
name = "storageClass.mounter"
value = "kernel"
},
{
name = "nodeplugin.podSecurityContext.runAsUser"
value = 0
},
{
name = "nodeplugin.podSecurityContext.runAsGroup"
value = 0
},
{
name = "provisioner.podSecurityContext.runAsUser"
value = 0
},
{
name = "provisioner.podSecurityContext.runAsGroup"
value = 0
},
{
name = "csiConfig[0].clusterID"
value = var.cephfs_csi.clusterid
},
{
name = "csiConfig[0].cephFS.subvolumeGroup"
value = var.cephfs_csi.subvolumegroup
},
# These should force the Pods to restart when userkey value changes.
# Mostly for troubleshooting, switching between ceph users.
{
name = "provisioner.podAnnotations.checksum\\/secret"
value = sha256(var.cephfs_csi.userkey)
},
{
name = "nodeplugin.podAnnotations.checksum\\/secret"
value = sha256(var.cephfs_csi.userkey)
}
]
set_list = [
{
name = "csiConfig[0].monitors"
value = var.cephfs_csi.monitors
},
{
name = "storageClass.mountOptions"
value = [
"ms_mode=secure"
]
}
]
}
이 경우 var.cluster_endpoint_domain은 Talos 클러스터의 VIP(가상 IP)로, 정상적인 컨트롤 노드 중 하나로 라우팅되도록 설정되어 있고, Terraform의 Helm provider에서 발생하는 제한 사항에 부딪힌 것 같다는 의심이 들기는 하네요.
전문가분들의 조언 부탁드립니다.