Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kubeconfig 수정정 #106

Merged
merged 1 commit into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bin/main/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ aes:
key: fb1755281b0ca6184a0ee644e6477ee7

cbtumblebug:
url: ${TUMBLEBUG_URL:210.217.178.130}
url: ${TUMBLEBUG_URL:13.125.215.182}
port: ${TUMBLEBUG_PORT:1323}
id: ${TUMBLEBUG_ID:default}
pass: ${TUMBLEBUG_PASSWORD:default}
Expand Down
19 changes: 0 additions & 19 deletions kubeconfig

This file was deleted.

20 changes: 17 additions & 3 deletions src/main/java/kr/co/mcmp/ape/cbtumblebug/dto/K8sClusterDto.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package kr.co.mcmp.ape.cbtumblebug.dto;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonProperty;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Map;
import lombok.ToString;

@Data
@NoArgsConstructor
@ToString
@AllArgsConstructor
@ApiModel(description = "K8s Cluster 정보")
public class K8sClusterDto {
Expand Down Expand Up @@ -69,6 +72,7 @@ public class K8sClusterDto {

@Data
@NoArgsConstructor
@ToString
@AllArgsConstructor
public static class ConnectionConfig {
@JsonProperty("configName")
Expand Down Expand Up @@ -105,6 +109,7 @@ public static class ConnectionConfig {
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public static class RegionZoneInfo {
@JsonProperty("assignedRegion")
private String assignedRegion;
Expand All @@ -116,6 +121,7 @@ public static class RegionZoneInfo {
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public static class RegionDetail {
@JsonProperty("regionId")
private String regionId;
Expand All @@ -136,6 +142,7 @@ public static class RegionDetail {
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public static class Location {
@JsonProperty("display")
private String display;
Expand All @@ -150,6 +157,7 @@ public static class Location {
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public static class CspViewK8sClusterDetail {
@JsonProperty("IId")
private IID iid;
Expand Down Expand Up @@ -180,6 +188,7 @@ public static class CspViewK8sClusterDetail {
}

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public static class IID {
Expand All @@ -191,6 +200,7 @@ public static class IID {
}

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public static class Network {
Expand All @@ -210,6 +220,7 @@ public static class Network {
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public static class NodeGroup {
@JsonProperty("IId")
private IID iid;
Expand Down Expand Up @@ -254,6 +265,7 @@ public static class NodeGroup {
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public static class AccessInfo {
@JsonProperty("Endpoint")
private String endpoint;
Expand All @@ -265,6 +277,7 @@ public static class AccessInfo {
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public static class Addons {
@JsonProperty("KeyValueList")
private List<KeyValue> keyValueList;
Expand All @@ -273,6 +286,7 @@ public static class Addons {
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public static class KeyValue {
@JsonProperty("key")
private String key;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,85 +1,115 @@
package kr.co.mcmp.softwarecatalog.kubernetes.service;

import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

import org.springframework.stereotype.Service;

import com.marcnuri.helm.Helm;
import com.marcnuri.helm.InstallCommand;
import com.marcnuri.helm.Release;

import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.KubernetesClient;
import kr.co.mcmp.ape.cbtumblebug.api.CbtumblebugRestApi;
import kr.co.mcmp.ape.cbtumblebug.dto.K8sClusterDto;
import kr.co.mcmp.softwarecatalog.SoftwareCatalog;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
@RequiredArgsConstructor
public class HelmChartService {
private final CbtumblebugRestApi api;

public Release deployHelmChart(String namespace, SoftwareCatalog catalog) {
public Release deployHelmChart(KubernetesClient client, String namespace, SoftwareCatalog catalog,
String clusterName) {
Path tempConfigFile = null;
K8sClusterDto dto = api.getK8sClusterByName(namespace, clusterName);
String cspType = dto.getConnectionConfig().getProviderName().toUpperCase();
log.info("CSP Type: {}", cspType);

try {
addHelmRepository(catalog);
String kubeconfig = dto.getCspViewK8sClusterDetail().getAccessInfo().getKubeconfig();

// Helm 설치 명령어 구성
InstallCommand installCommand = Helm.install(
catalog.getHelmChart().getRepositoryName() + "/" + catalog.getHelmChart().getChartName())
.withName(catalog.getHelmChart().getChartName())
.withNamespace(namespace)
.withVersion(catalog.getHelmChart().getChartVersion())
.set("replicaCount", catalog.getMinReplicas())
.set("image.repository", catalog.getHelmChart().getImageRepository())
.set("image.tag", "latest")
.set("image.pullPolicy", "Always")
.set("service.port", catalog.getDefaultPort())
.set("resources.requests.cpu", catalog.getMinCpu().toString())
.set("resources.requests.memory", catalog.getMinMemory() + "Mi")
.set("resources.limits.cpu", catalog.getRecommendedCpu().toString())
.set("resources.limits.memory", catalog.getRecommendedMemory() + "Mi");

// HPA 설정 추가
// GCP의 경우 gke-gcloud-auth-plugin 관련 설정 제거
if ("GCP".equalsIgnoreCase(cspType)) {
kubeconfig = kubeconfig.replaceAll("command:\\s*gke-gcloud-auth-plugin", "")
.replaceAll("apiVersion:\\s*client.authentication.k8s.io/.*\\n", "")
.replaceAll("installHint:.*\\n", "")
.replaceAll("provideClusterInfo:.*\\n", "");
}
tempConfigFile = createTempKubeconfigFile(kubeconfig);

InstallCommand installCommand = createInstallCommand(catalog, namespace, tempConfigFile);
applyCspSpecificSettings(installCommand, cspType);

// HPA 설정
if (Boolean.TRUE.equals(catalog.getHpaEnabled())) {
installCommand
.set("autoscaling.enabled", true)
.set("autoscaling.minReplicas", catalog.getMinReplicas())
.set("autoscaling.maxReplicas", catalog.getMaxReplicas())
.set("autoscaling.targetCPUUtilizationPercentage", catalog.getCpuThreshold().intValue())
.set("autoscaling.targetMemoryUtilizationPercentage", catalog.getMemoryThreshold().intValue());
.set("autoscaling.targetCPUUtilizationPercentage", catalog.getCpuThreshold())
.set("autoscaling.targetMemoryUtilizationPercentage", catalog.getMemoryThreshold());
}

// Helm 차트 설치 실행

Release result = installCommand.call();

log.info("Helm Chart '{}' 버전 '{}'가 네임스페이스 '{}'에 배포됨 (HPA: {})",
catalog.getHelmChart().getChartName(),
"latest",
namespace,
catalog.getHpaEnabled());
log.info("Helm Chart '{}' 배포 완료 - namespace: {}, CSP: {}",
catalog.getHelmChart().getChartName(),
namespace,
cspType);
return result;

} catch (Exception e) {
log.error("Helm Chart 배포 중 오류 발생", e);
log.error("Helm Chart 배포 중 오류 발생 - CSP: {}", cspType, e);
throw new RuntimeException("Helm Chart 배포 실패", e);
} finally {
deleteTempFile(tempConfigFile);
}
}

public void uninstallHelmChart(String namespace, SoftwareCatalog catalog) {
try {
String result = Helm.uninstall(catalog.getHelmChart().getChartName())

private InstallCommand createInstallCommand(SoftwareCatalog catalog, String namespace, Path configFile) {
return Helm.install(catalog.getHelmChart().getRepositoryName() + "/" + catalog.getHelmChart().getChartName())
.withKubeConfig(configFile)
.withName(catalog.getHelmChart().getChartName())
.withNamespace(namespace)
.call();

boolean deleted = result != null && !result.isEmpty();

if (deleted) {
log.info("Helm Release '{}' 가 네임스페이스 '{}'에서 삭제됨",
catalog.getHelmChart().getChartName(), namespace);
} else {
log.warn("Helm Release '{}' 삭제 실패",
catalog.getHelmChart().getChartName());
}
} catch (Exception e) {
log.error("Helm Release 삭제 중 오류 발생", e);
throw new RuntimeException("Helm Release 삭제 실패", e);
.withVersion(catalog.getHelmChart().getChartVersion())
.set("replicaCount", catalog.getMinReplicas())
.set("image.repository", catalog.getHelmChart().getImageRepository())
.set("image.tag", "latest")
.set("image.pullPolicy", "Always")
.set("service.port", catalog.getDefaultPort())
.set("resources.requests.cpu", catalog.getMinCpu().toString())
.set("resources.requests.memory", catalog.getMinMemory() + "Mi")
.set("resources.limits.cpu", catalog.getRecommendedCpu().toString())
.set("resources.limits.memory", catalog.getRecommendedMemory() + "Mi")
.set("persistence.enabled", false)
.set("securityContext.enabled", false)
.set("serviceAccount.create", true)
.withTimeout(300)
.waitReady();
}

private void applyCspSpecificSettings(InstallCommand command, String cspType) {
log.info("Applying CSP specific settings for: {}", cspType);
switch (cspType) {
case "GCP":
command.set("gcp.auth.enabled", false)
.set("serviceAccount.annotations.iam\\.gke\\.io/gcp-service-account", "false")
.set("rbac.create", true);
break;
case "AZURE":
command.set("azure.auth.enabled", false)
.set("serviceAccount.annotations.azure\\.workload\\.identity/use", "false");
break;
default:
log.warn("알 수 없는 CSP 타입: {}", cspType);
}
}

Expand All @@ -90,4 +120,54 @@ private void addHelmRepository(SoftwareCatalog catalog) throws Exception {
.call();
Helm.repo().update();
}
}

private Path createTempKubeconfigFile(String kubeconfig) throws IOException {
Path tempFile = Files.createTempFile("kubeconfig", ".yaml");
Files.write(tempFile, kubeconfig.getBytes(StandardCharsets.UTF_8));
return tempFile;
}

private void deleteTempFile(Path tempFile) {
if (tempFile != null) {
try {
Files.deleteIfExists(tempFile);
} catch (IOException e) {
log.warn("임시 파일 삭제 실패: {}", tempFile, e);
}
}
}

public void uninstallHelmChart(String namespace, SoftwareCatalog catalog, String clusterName) {
Path tempConfigFile = null;
try {
K8sClusterDto dto = api.getK8sClusterByName(namespace, clusterName);
String cspType = dto.getConnectionConfig().getProviderName().toUpperCase();
String kubeconfig = dto.getCspViewK8sClusterDetail().getAccessInfo().getKubeconfig();

// GCP의 경우 gke-gcloud-auth-plugin 관련 설정 제거
if ("GCP".equalsIgnoreCase(cspType)) {
kubeconfig = kubeconfig.replaceAll("command:\\s*gke-gcloud-auth-plugin", "")
.replaceAll("apiVersion:\\s*client.authentication.k8s.io/.*\\n", "")
.replaceAll("installHint:.*\\n", "")
.replaceAll("provideClusterInfo:.*\\n", "");
}
tempConfigFile = createTempKubeconfigFile(kubeconfig);

String result = Helm.uninstall(catalog.getHelmChart().getChartName())
.withKubeConfig(tempConfigFile)
.withNamespace(namespace)
.call();

log.info("Helm Release '{}' 삭제 완료 - namespace: {}, CSP: {}",
catalog.getHelmChart().getChartName(),
namespace,
cspType);

} catch (Exception e) {
log.error("Helm Release 삭제 실패", e);
throw new RuntimeException("Helm Release 삭제 실패", e);
} finally {
deleteTempFile(tempConfigFile);
}
}
}
Loading