관리 메뉴

피터의 개발이야기

[kubernetes] CDK8s 다중 클러스터 생성 방법(feat. cdk8s example) 본문

Kubernetes/cdk8s

[kubernetes] CDK8s 다중 클러스터 생성 방법(feat. cdk8s example)

기록하는 백앤드개발자 2024. 2. 14. 20:29
반응형

ㅁ 들어가며

[kubernetes] cdk8s란 무엇인가요?에서 cdk8s 개발환경을 설정하였고, 단일 클러스터의 yaml 생성과정을 알아보았다.

ㅇ 이 글에서는 cdk8s-team의 example 중에 cdk8s-composition을 토대로 다중 클러스터를 관리하는 방법에 대해서 정리하였다.

cdk8s-team example - java/cdk8s-composition

ㅇ 이 글에서 작성한 코드는 이곳에 있다.

ㅁ 다중 클러스터 생성을 위한 Template와 Value의 구분

 ㅇ 다중클러스터의 생성을 위해서는 공통되는 부분과 동적으로 변동되는 부분이 있다.

 ㅇ Helm에 비유하자면,
    - 공통되는 부분은 Template이고,

    - 변동되는 부분은 value.yaml이다.

ㅇ 예제에서는
    - value => WebServiceProps

    - Template => WebService

    - template + value  => WebServices
  구성되어 있다.

 

ㅁ 단일 클러스터 yaml 생성 소스

package com.peterica.app;

import imports.k8s.*;
import software.constructs.Construct;

import org.cdk8s.App;
import org.cdk8s.Chart;
import org.cdk8s.ChartProps;

import java.util.Collections;
import java.util.List;
import java.util.Map;

public class Main extends Chart
{

    public Main(final Construct scope, final String id, final String appLabel) {
        this(scope, id, null, appLabel);
    }

    public Main(final Construct scope, final String id, final ChartProps options, final String appLabel) {
        super(scope, id, options);

        Map<String, String> label = Collections.singletonMap("app", appLabel);

        KubeDeployment kubeDeployment = new KubeDeployment(this, "my-deployment", KubeDeploymentProps.builder()
                .spec(DeploymentSpec.builder()
                        .replicas(3)
                        .selector(LabelSelector.builder()
                                .matchLabels(label)
                                .build())
                        .template(PodTemplateSpec.builder()
                                .metadata(ObjectMeta.builder().labels(label)
                                        .build())
                                .spec(PodSpec.builder()
                                        .containers(List.of(Container.builder()
                                                .name("app-container-test")
                                                .image("nginx:1.19.10")
                                                .ports(List.of(ContainerPort.builder()
                                                        .containerPort(80)
                                                        .build()))
                                                .build()))
                                        .build())
                                .build())
                        .build())
                .build());

        // service 생성문 생성
        KubeService kubeService = new KubeService(this, "my-sevice", KubeServiceProps.builder()
                .spec(ServiceSpec.builder()
                        .type("LoadBalancer") // 아직 모를 수 있는데, enum이 있을 줄 알았는데 없어서 아쉬움.
                        .ports(List.of(ServicePort.builder()
                                .port(80)
                                .targetPort(IntOrString.fromNumber(80))
                                .build()))
                        .selector(label)
                        .build())
                .build());
    }

    public static void main(String[] args) {
        final App app = new App();
        new Main(app, "getting-started", "my-app");
        app.synth();
    }
}

 ㅇ Main으로 단일 클러스터 생성을 위한 소스코드이다.

 ㅇ 기본적으로 chart를 상속받아서 쿠버네티스의 오브젝트들을 빌드하고 있다.

 

ㅁ Values - WebServiceProps

package com.peterica.app.composition;

public class WebServiceProps {

  private String image;
  private int replicas;
  private int port;
  private int containerPort;

  public WebServiceProps(final String image, final int replicas, final int port, final int containerPort) {
    this.image = image;
    this.replicas = replicas;
    this.port = port;
    this.containerPort = containerPort;
  }

  public String getImage() {
    return this.image;
  }

  public int getReplicas() {
    return this.replicas;
  }

  public int getPort() {
    return this.port;
  }

  public int getContainerPort() {
    return this.containerPort;
  }

  public static final class Builder {
    private String image;
    private int replicas = 1;
    private int port = 80;
    private int containerPort = 8080;

    public Builder image(String image) {
      this.image = image;
      return this;
    }

    public Builder replicas(int replicas) {
      this.replicas = replicas;
      return this;
    }

    public Builder port(int port) {
      this.port = port;
      return this;
    }

    public Builder containerPort(int containerPort) {
      this.containerPort = containerPort;
      return this;
    }

    public WebServiceProps build() {
      return new WebServiceProps(image, replicas, port, containerPort);
    }
  }
}

 ㅇ 다중클러스터의 생성을 위해서는 공통되는 부분과 동적으로 변동되는 부분이 있다.

 ㅇ 이 변동되는 부분을 Props Dto형태로 선언하였다.

 ㅇ Helm에 비유하자면, 공통되는 부분은 Template이고, 변동되는 부분은 value.yaml인데, props는 이 value에 해당한다.

 ㅇ 이번에는 Template에 해당하는 부분을 설명하겠다.

 

ㅁ Template- WebService

package com.peterica.app.composition;

import imports.k8s.*;
import org.cdk8s.Names;
import software.constructs.Construct;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * cdk8s 공통 인수, prop 상속받는 코딩 연습용.
 * 레퍼런스: https://github.com/cdk8s-team/cdk8s-examples/java/cdk8s-composition
 */

public class WebService extends Construct {

    public WebService(final Construct scope, final String id){
        this(scope, id, null);
    }

    public WebService(final Construct scope, final String id, final WebServiceProps props){
        super(scope, id);

        Map<String, String> label = Collections.singletonMap("app", Names.toLabelValue(this));

        new KubeService(this, "service", KubeServiceProps.builder()
                .spec(ServiceSpec.builder()
                        .type("LoadBalancer")
                        .ports(List.of(ServicePort.builder()
                                .port(props.getPort())
                                .targetPort(IntOrString.fromNumber(props.getContainerPort()))
                                .build()))
                        .selector(label)
                        .build())
                .build());

        new KubeDeployment(this, "deployment", KubeDeploymentProps.builder()
                .spec(DeploymentSpec.builder()
                        .replicas(props.getReplicas())
                        .selector(LabelSelector.builder()
                                .matchLabels(label)
                                .build())
                        .template(PodTemplateSpec.builder()
                                .metadata(ObjectMeta.builder()
                                        .labels(label)
                                        .build())
                                .spec(PodSpec.builder()
                                        .containers(List.of(Container.builder()
                                                        .name("web")
                                                        .image(props.getImage())
                                                        .ports(List.of(ContainerPort.builder()
                                                                        .containerPort(props.getContainerPort())
                                                                .build()))
                                                .build()))
                                        .build())
                                .build())
                        .build())
                .build());
    }
}

 

 ㅇ 어떤 리소스를 클러스터에 배포할지를 정의하고 있다. 

 ㅇ Deployment와 Service를 생성하고 있으며, 변동되는 부분은 Props를 참조하고 있다.

 

ㅁ Template + Props를 결합 - 개별 클러스터 생성

package com.peterica.app.composition;

import software.constructs.Construct;

import org.cdk8s.App;
import org.cdk8s.Chart;
import org.cdk8s.ChartProps;

public class WebServices extends Chart {

        public WebServices(final Construct scope, final String id) {
                this(scope, id, null);
        }

        public WebServices(final Construct scope, final String id, final ChartProps props) {
                super(scope, id, props);

                // Template + Props를 결합 - 개별 클러스터 생성
                new WebService(this, "hello", new WebServiceProps.Builder()
                                .image("paulbouwer/hello-kubernetes:1.7")
                                .replicas(2)
                                .build());

                new WebService(this, "ghost", new WebServiceProps.Builder()
                                .image("ghost")
                                .containerPort(2368)
                                .build());

        }

        public static void main(String[] args) {

                final App app = new App();
                new WebServices(app, "web-services");
                app.synth();

        }
}

 

 ㅇ hello, ghost라는 두개의 클러스터를 생성하는 로직이다.

 ㅇ WebService(Template)에 Props(values)를 경합하여 다중 클러스터의 yaml를 생성하였다.

 

ㅁ yaml 생성

$  cdk8s synth

 

 

apiVersion: v1
kind: Service
metadata:
  name: web-services-hello-service-c8867cc5
spec:
  ports:
    - port: 80
      targetPort: 8080
  selector:
    app: web-services-hello-c8c4e53d
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-services-hello-deployment-c8aa3bdf
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web-services-hello-c8c4e53d
  template:
    metadata:
      labels:
        app: web-services-hello-c8c4e53d
    spec:
      containers:
        - image: paulbouwer/hello-kubernetes:1.7
          name: web
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: web-services-ghost-service-c88ea138
spec:
  ports:
    - port: 80
      targetPort: 2368
  selector:
    app: web-services-ghost-c88fcf47
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-services-ghost-deployment-c8edd418
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web-services-ghost-c88fcf47
  template:
    metadata:
      labels:
        app: web-services-ghost-c88fcf47
    spec:
      containers:
        - image: ghost
          name: web
          ports:
            - containerPort: 2368

 ㅇ ghost와 hello 클러스터를 위한 yaml 파일을 확인할 수 있다.

 

ㅁ 함께 보면 좋은 사이트

cdk8s-examples

피터의 개발이야기 github

반응형
Comments