Skip to content

Commit be1d8e9

Browse files
authored
Merge pull request #34 from boostcampwm-2024/feature-be-#26
[#26] Pod 생성 및 삭제 이벤트 발생 구독
2 parents fa1ea30 + b1d6807 commit be1d8e9

File tree

7 files changed

+140
-89
lines changed

7 files changed

+140
-89
lines changed

DBManager/package-lock.json

Lines changed: 18 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

DBManager/src/K8S/KubernetesService.ts

Lines changed: 0 additions & 62 deletions
This file was deleted.

DBManager/src/app.controller.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
1-
import { Controller, Delete, Get, Query } from '@nestjs/common';
2-
import { KubernetesService } from './K8S/KubernetesService';
1+
import { Controller, Delete, Get, Param, Query } from '@nestjs/common';
2+
import { K8SApiService } from './k8s/K8SApi.service';
33

44
@Controller()
55
export class AppController {
6-
constructor(private readonly kubernetesService: KubernetesService) {}
6+
constructor(private readonly k8SApiService: K8SApiService) {}
77

88
@Get('/pods')
99
async getAllPods() {
10-
const pods = await this.kubernetesService.getAllPods();
10+
const pods = await this.k8SApiService.getAllPods();
1111
return pods;
1212
}
1313

1414
@Get('/create-pod')
1515
async createPod() {
16-
const pod = await this.kubernetesService.createPod();
16+
const pod = await this.k8SApiService.createPod();
1717
return pod;
1818
}
1919

2020
@Delete('/delete-pod')
2121
async deletePod(@Query('podName') podName: string) {
2222
console.log(podName);
23-
const pod = await this.kubernetesService.deletePod(podName);
23+
const pod = await this.k8SApiService.deletePod(podName);
2424
return pod;
2525
}
2626
}

DBManager/src/app.module.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import { Module } from '@nestjs/common';
22
import { AppController } from './app.controller';
3-
import { KubernetesService } from './K8S/KubernetesService';
43
import { ConfigModule } from '@nestjs/config';
4+
import { K8SApiModule } from './k8s/K8SApi.module';
55

66
@Module({
77
imports: [
88
ConfigModule.forRoot({
99
isGlobal: true,
1010
}),
11+
K8SApiModule,
1112
],
1213
controllers: [AppController],
13-
providers: [KubernetesService],
14+
providers: [],
1415
})
1516
export class AppModule {}

DBManager/src/config/redis/redis.service.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,14 @@ export class RedisService {
3636
return this.podConnection.hget(key, field);
3737
}
3838

39-
async hsetPod(key: string, field: string, value: number): Promise<void> {
39+
async hsetPod(key: string, field: string, value: number | string): Promise<void> {
4040
await this.podConnection.hset(key, field, value);
4141
}
4242

43+
async delPod(key: string): Promise<void> {
44+
await this.podConnection.del(key);
45+
}
46+
4347
async subscribeActiveUser(
4448
channel: string,
4549
onMessage: (message: string) => void,

DBManager/src/k8s/K8SApi.module.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Module } from '@nestjs/common';
2+
import { K8SApiService } from './K8SApi.service';
3+
import { RedisModule } from 'src/config/redis/redis.module';
4+
5+
@Module({
6+
imports: [RedisModule],
7+
exports: [K8SApiService],
8+
providers: [K8SApiService],
9+
})
10+
export class K8SApiModule {}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { Injectable, OnModuleInit } from '@nestjs/common';
2+
import * as k8s from '@kubernetes/client-node';
3+
import { RedisService } from 'src/config/redis/redis.service';
4+
5+
@Injectable()
6+
export class K8SApiService {
7+
private podCnt = 0;
8+
private k8sApi;
9+
private k8sWatch : k8s.Watch;
10+
private namespace = 'default';
11+
12+
constructor(private readonly redisService: RedisService) {}
13+
14+
async onModuleInit() {
15+
const kc = new k8s.KubeConfig();
16+
kc.loadFromDefault();
17+
this.k8sApi = kc.makeApiClient(k8s.CoreV1Api);
18+
this.k8sWatch = new k8s.Watch(kc);
19+
this.startWatchPod();
20+
}
21+
22+
async getPodIp(podName: string): Promise<string> {
23+
const podInfo = await this.k8sApi.readNamespacedPod(podName, this.namespace);
24+
return podInfo.body.status.podIP || 'Pending';
25+
}
26+
27+
startWatchPod() {
28+
const path = `/api/v1/namespaces/${this.namespace}/pods`;
29+
const queryParams = {
30+
allowWatchBookmarks: true,
31+
labelSelector: 'app=mysql',
32+
};
33+
const handlePodEvent = async (type : String, apiObj: any, watchObj: any) => {
34+
const podName = watchObj.object.metadata.name;
35+
const podStatus = watchObj.object.status;
36+
const curPodIp = await this.redisService.hgetPod(podName, 'podIp');
37+
38+
if (type === 'ADDED') {
39+
await this.redisService.hsetPod(podName, 'activeUser', 0);
40+
await this.redisService.hsetPod(podName, 'podIp', podStatus.podIp || '');
41+
} else if (type === 'MODIFIED' && podStatus.podIP && curPodIp == '') {
42+
const podIp = podStatus.podIP;
43+
await this.redisService.hsetPod(podName, 'podIp', podIp);
44+
} else if (type === 'DELETED') {
45+
await this.redisService.delPod(podName);
46+
}
47+
};
48+
49+
this.k8sWatch.watch(path, queryParams, handlePodEvent, err => {});
50+
}
51+
52+
async createPod() {
53+
const mysqlPod = {
54+
metadata: {
55+
generateName: 'mysql-',
56+
labels: {
57+
app: 'mysql',
58+
},
59+
},
60+
spec: {
61+
containers: [
62+
{
63+
name: 'mysql',
64+
image: 'mysql',
65+
},
66+
],
67+
},
68+
};
69+
70+
const createdPod = await this.k8sApi.createNamespacedPod(this.namespace, mysqlPod);
71+
return createdPod;
72+
}
73+
74+
async deletePod(podName: string) {
75+
const deletePod = await this.k8sApi.deleteNamespacedPod(podName, this.namespace);
76+
return deletePod;
77+
}
78+
79+
async getAllPods() {
80+
const podList = await this.k8sApi.listNamespacedPod(this.namespace);
81+
const podResult = {};
82+
83+
for (const pod of podList.body.items) {
84+
const podName = pod.metadata.name;
85+
console.log(podName);
86+
87+
const podInfo = await this.k8sApi.readNamespacedPod(podName, this.namespace);
88+
const podIp = podInfo.body.status.podIP;
89+
console.log(podIp);
90+
91+
podResult[podName] = podIp;
92+
}
93+
return {
94+
podCnt : Object.keys(podResult).length,
95+
podResult,
96+
};
97+
}
98+
}

0 commit comments

Comments
 (0)