push k8s logs to LOG SERVICE IP
parent
50d7f57f9d
commit
2e2eae0acf
|
@ -3262,6 +3262,8 @@ const cloud_runner_logger_1 = __importDefault(__nccwpck_require__(42864));
|
||||||
const cloud_runner_1 = __importDefault(__nccwpck_require__(79144));
|
const cloud_runner_1 = __importDefault(__nccwpck_require__(79144));
|
||||||
const remote_client_logger_1 = __nccwpck_require__(59412);
|
const remote_client_logger_1 = __nccwpck_require__(59412);
|
||||||
const kubernetes_role_1 = __nccwpck_require__(88231);
|
const kubernetes_role_1 = __nccwpck_require__(88231);
|
||||||
|
const kubernetes_log_service_1 = __importDefault(__nccwpck_require__(62552));
|
||||||
|
const cloud_runner_system_1 = __nccwpck_require__(4197);
|
||||||
class Kubernetes {
|
class Kubernetes {
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
constructor(buildParameters) {
|
constructor(buildParameters) {
|
||||||
|
@ -3277,19 +3279,23 @@ class Kubernetes {
|
||||||
this.kubeConfig = new k8s.KubeConfig();
|
this.kubeConfig = new k8s.KubeConfig();
|
||||||
this.kubeConfig.loadFromDefault();
|
this.kubeConfig.loadFromDefault();
|
||||||
this.kubeClient = this.kubeConfig.makeApiClient(k8s.CoreV1Api);
|
this.kubeClient = this.kubeConfig.makeApiClient(k8s.CoreV1Api);
|
||||||
|
this.kubeClientApps = this.kubeConfig.makeApiClient(k8s.AppsV1Api);
|
||||||
this.kubeClientBatch = this.kubeConfig.makeApiClient(k8s.BatchV1Api);
|
this.kubeClientBatch = this.kubeConfig.makeApiClient(k8s.BatchV1Api);
|
||||||
this.rbacAuthorizationV1Api = this.kubeConfig.makeApiClient(k8s.RbacAuthorizationV1Api);
|
this.rbacAuthorizationV1Api = this.kubeConfig.makeApiClient(k8s.RbacAuthorizationV1Api);
|
||||||
this.namespace = 'default';
|
this.namespace = 'default';
|
||||||
cloud_runner_logger_1.default.log('Loaded default Kubernetes configuration for this environment');
|
cloud_runner_logger_1.default.log('Loaded default Kubernetes configuration for this environment');
|
||||||
}
|
}
|
||||||
async PushLogUpdate(logs) {
|
async PushLogUpdate(logs) {
|
||||||
const body = new k8s.V1ConfigMap();
|
// push logs to nginx file server via 'LOG_SERVICE_IP' env var
|
||||||
body.data = {};
|
const ip = process.env[`LOG_SERVICE_IP`];
|
||||||
body.data['logs'] = logs;
|
if (ip === undefined) {
|
||||||
body.metadata = { name: `${this.jobName}-logs`, namespace: this.namespace, labels: { app: 'unity-builder' } };
|
remote_client_logger_1.RemoteClientLogger.logWarning(`LOG_SERVICE_IP not set, skipping log push`);
|
||||||
remote_client_logger_1.RemoteClientLogger.log(`Pushing to Kubernetes ConfigMap`);
|
return;
|
||||||
await this.kubeClient.createNamespacedConfigMap(this.namespace, body);
|
}
|
||||||
remote_client_logger_1.RemoteClientLogger.log(`Pushed logs to Kubernetes ConfigMap`);
|
const url = `http://${ip}/api/log`;
|
||||||
|
remote_client_logger_1.RemoteClientLogger.log(`Pushing logs to ${url}`);
|
||||||
|
const response = await cloud_runner_system_1.CloudRunnerSystem.Run(`curl -X POST -d "${logs}" ${url}`, false, true);
|
||||||
|
remote_client_logger_1.RemoteClientLogger.log(`Pushed logs to ${url} ${response}`);
|
||||||
}
|
}
|
||||||
async listResources() {
|
async listResources() {
|
||||||
const pods = await this.kubeClient.listNamespacedPod(this.namespace);
|
const pods = await this.kubeClient.listNamespacedPod(this.namespace);
|
||||||
|
@ -3410,9 +3416,10 @@ class Kubernetes {
|
||||||
async createNamespacedJob(commands, image, mountdir, workingdir, environment, secrets) {
|
async createNamespacedJob(commands, image, mountdir, workingdir, environment, secrets) {
|
||||||
for (let index = 0; index < 3; index++) {
|
for (let index = 0; index < 3; index++) {
|
||||||
try {
|
try {
|
||||||
const jobSpec = kubernetes_job_spec_factory_1.default.getJobSpec(commands, image, mountdir, workingdir, environment, secrets, this.buildGuid, this.buildParameters, this.secretName, this.pvcName, this.jobName, k8s, this.containerName);
|
const ip = await kubernetes_log_service_1.default.createLogDeployment(this.namespace, this.kubeClientApps, this.kubeClient);
|
||||||
|
const jobSpec = kubernetes_job_spec_factory_1.default.getJobSpec(commands, image, mountdir, workingdir, environment, secrets, this.buildGuid, this.buildParameters, this.secretName, this.pvcName, this.jobName, k8s, this.containerName, ip);
|
||||||
await new Promise((promise) => setTimeout(promise, 15000));
|
await new Promise((promise) => setTimeout(promise, 15000));
|
||||||
await kubernetes_role_1.KubernetesRole.createRole(this.serviceAccountName, this.namespace, this.rbacAuthorizationV1Api);
|
// await KubernetesRole.createRole(this.serviceAccountName, this.namespace, this.rbacAuthorizationV1Api);
|
||||||
const result = await this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
const result = await this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
||||||
cloud_runner_logger_1.default.log(`Build job created`);
|
cloud_runner_logger_1.default.log(`Build job created`);
|
||||||
await new Promise((promise) => setTimeout(promise, 5000));
|
await new Promise((promise) => setTimeout(promise, 5000));
|
||||||
|
@ -3499,7 +3506,7 @@ const client_node_1 = __nccwpck_require__(89679);
|
||||||
const command_hook_service_1 = __nccwpck_require__(96159);
|
const command_hook_service_1 = __nccwpck_require__(96159);
|
||||||
const cloud_runner_1 = __importDefault(__nccwpck_require__(79144));
|
const cloud_runner_1 = __importDefault(__nccwpck_require__(79144));
|
||||||
class KubernetesJobSpecFactory {
|
class KubernetesJobSpecFactory {
|
||||||
static getJobSpec(command, image, mountdir, workingDirectory, environment, secrets, buildGuid, buildParameters, secretName, pvcName, jobName, k8s, containerName) {
|
static getJobSpec(command, image, mountdir, workingDirectory, environment, secrets, buildGuid, buildParameters, secretName, pvcName, jobName, k8s, containerName, ip = '') {
|
||||||
const job = new k8s.V1Job();
|
const job = new k8s.V1Job();
|
||||||
job.apiVersion = 'batch/v1';
|
job.apiVersion = 'batch/v1';
|
||||||
job.kind = 'Job';
|
job.kind = 'Job';
|
||||||
|
@ -3557,6 +3564,7 @@ class KubernetesJobSpecFactory {
|
||||||
environmentVariable.valueFrom = secret;
|
environmentVariable.valueFrom = secret;
|
||||||
return environmentVariable;
|
return environmentVariable;
|
||||||
}),
|
}),
|
||||||
|
{ name: 'LOG_SERVICE_IP', value: ip },
|
||||||
],
|
],
|
||||||
volumeMounts: [
|
volumeMounts: [
|
||||||
{
|
{
|
||||||
|
@ -3598,6 +3606,180 @@ class KubernetesJobSpecFactory {
|
||||||
exports["default"] = KubernetesJobSpecFactory;
|
exports["default"] = KubernetesJobSpecFactory;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 62552:
|
||||||
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
const k8s = __importStar(__nccwpck_require__(89679));
|
||||||
|
class KubernetesLogService {
|
||||||
|
// static async function, creates a deployment and service
|
||||||
|
static async createLogService(serviceAccountName, namespace, kubeClient) {
|
||||||
|
const serviceAccount = new k8s.V1ServiceAccount();
|
||||||
|
serviceAccount.apiVersion = 'v1';
|
||||||
|
serviceAccount.kind = 'ServiceAccount';
|
||||||
|
serviceAccount.metadata = {
|
||||||
|
name: serviceAccountName,
|
||||||
|
};
|
||||||
|
serviceAccount.automountServiceAccountToken = true;
|
||||||
|
return kubeClient.createNamespacedServiceAccount(namespace, serviceAccount);
|
||||||
|
}
|
||||||
|
static async deleteLogService(serviceAccountName, namespace, kubeClient) {
|
||||||
|
await kubeClient.deleteNamespacedServiceAccount(serviceAccountName, namespace);
|
||||||
|
}
|
||||||
|
static async createLogDeployment(namespace, kubeClient, kubeClientCore) {
|
||||||
|
// json
|
||||||
|
/*
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
service: http-fileserver
|
||||||
|
name: http-fileserver
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy: {}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
service: http-fileserver
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: my-docker-hub-account/http-fileserver-kubernetes:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
name: http-fileserver
|
||||||
|
resources: {}
|
||||||
|
restartPolicy: Always
|
||||||
|
status: {}
|
||||||
|
*/
|
||||||
|
// create a deployment with above json
|
||||||
|
const deployment = new k8s.V1Deployment();
|
||||||
|
deployment.apiVersion = 'apps/v1';
|
||||||
|
deployment.kind = 'Deployment';
|
||||||
|
deployment.metadata = {
|
||||||
|
name: 'http-fileserver',
|
||||||
|
labels: {
|
||||||
|
service: 'http-fileserver',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
deployment.spec = {
|
||||||
|
selector: {
|
||||||
|
matchLabels: {
|
||||||
|
service: 'http-fileserver',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
replicas: 1,
|
||||||
|
strategy: {},
|
||||||
|
template: {
|
||||||
|
metadata: {
|
||||||
|
labels: {
|
||||||
|
service: 'http-fileserver',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
spec: {
|
||||||
|
containers: [
|
||||||
|
{
|
||||||
|
image: 'my-docker-hub-account/http-fileserver-kubernetes:latest',
|
||||||
|
imagePullPolicy: 'Always',
|
||||||
|
name: 'http-fileserver',
|
||||||
|
resources: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
restartPolicy: 'Always',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
await kubeClient.createNamespacedDeployment(namespace, deployment);
|
||||||
|
await this.createLogServiceExpose(namespace, kubeClientCore);
|
||||||
|
// wait in loop until serivce ip address is exposed
|
||||||
|
for (let index = 0; index < 10; index++) {
|
||||||
|
// wait for service to share ip address
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 10000));
|
||||||
|
// get ip address of service
|
||||||
|
const service = await kubeClientCore.readNamespacedService('http-fileserver', namespace);
|
||||||
|
const ip = service.body.status?.loadBalancer?.ingress?.[0]?.ip;
|
||||||
|
if (ip) {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// create kubernetes service to expose deployment
|
||||||
|
static async createLogServiceExpose(namespace, kubeClient) {
|
||||||
|
// json
|
||||||
|
/*
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
service: http-fileserver
|
||||||
|
name: http-fileserver
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: 80-80
|
||||||
|
port: 80
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 80
|
||||||
|
selector:
|
||||||
|
service: http-fileserver
|
||||||
|
type: LoadBalancer
|
||||||
|
status:
|
||||||
|
loadBalancer: {}
|
||||||
|
*/
|
||||||
|
// create a service with above json
|
||||||
|
const service = new k8s.V1Service();
|
||||||
|
service.apiVersion = 'v1';
|
||||||
|
service.kind = 'Service';
|
||||||
|
service.metadata = {
|
||||||
|
name: 'http-fileserver',
|
||||||
|
labels: {
|
||||||
|
service: 'http-fileserver',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
service.spec = {
|
||||||
|
ports: [
|
||||||
|
{
|
||||||
|
name: '80-80',
|
||||||
|
port: 80,
|
||||||
|
protocol: 'TCP',
|
||||||
|
targetPort: 80,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selector: {
|
||||||
|
service: 'http-fileserver',
|
||||||
|
},
|
||||||
|
type: 'LoadBalancer',
|
||||||
|
};
|
||||||
|
await kubeClient.createNamespacedService(namespace, service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports["default"] = KubernetesLogService;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 90740:
|
/***/ 90740:
|
||||||
|
@ -4621,6 +4803,7 @@ class RemoteClientLogger {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cloud_runner_logger_1.default.log(`Collected Logs`);
|
cloud_runner_logger_1.default.log(`Collected Logs`);
|
||||||
|
cloud_runner_logger_1.default.log(process.env[`LOG_SERVICE_IP`] || ``);
|
||||||
const logs = node_fs_1.default.readFileSync(RemoteClientLogger.LogFilePath).toString();
|
const logs = node_fs_1.default.readFileSync(RemoteClientLogger.LogFilePath).toString();
|
||||||
cloud_runner_logger_1.default.log(logs);
|
cloud_runner_logger_1.default.log(logs);
|
||||||
await k8s_1.default.Instance.PushLogUpdate(logs);
|
await k8s_1.default.Instance.PushLogUpdate(logs);
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -16,11 +16,14 @@ import { ProviderResource } from '../provider-resource';
|
||||||
import { ProviderWorkflow } from '../provider-workflow';
|
import { ProviderWorkflow } from '../provider-workflow';
|
||||||
import { RemoteClientLogger } from '../../remote-client/remote-client-logger';
|
import { RemoteClientLogger } from '../../remote-client/remote-client-logger';
|
||||||
import { KubernetesRole } from './kubernetes-role';
|
import { KubernetesRole } from './kubernetes-role';
|
||||||
|
import KubernetesLogService from './kubernetes-log-service';
|
||||||
|
import { CloudRunnerSystem } from '../../services/core/cloud-runner-system';
|
||||||
|
|
||||||
class Kubernetes implements ProviderInterface {
|
class Kubernetes implements ProviderInterface {
|
||||||
public static Instance: Kubernetes;
|
public static Instance: Kubernetes;
|
||||||
public kubeConfig!: k8s.KubeConfig;
|
public kubeConfig!: k8s.KubeConfig;
|
||||||
public kubeClient!: k8s.CoreV1Api;
|
public kubeClient!: k8s.CoreV1Api;
|
||||||
|
public kubeClientApps!: k8s.AppsV1Api;
|
||||||
public kubeClientBatch!: k8s.BatchV1Api;
|
public kubeClientBatch!: k8s.BatchV1Api;
|
||||||
public rbacAuthorizationV1Api!: k8s.RbacAuthorizationV1Api;
|
public rbacAuthorizationV1Api!: k8s.RbacAuthorizationV1Api;
|
||||||
public buildGuid: string = '';
|
public buildGuid: string = '';
|
||||||
|
@ -40,6 +43,7 @@ class Kubernetes implements ProviderInterface {
|
||||||
this.kubeConfig = new k8s.KubeConfig();
|
this.kubeConfig = new k8s.KubeConfig();
|
||||||
this.kubeConfig.loadFromDefault();
|
this.kubeConfig.loadFromDefault();
|
||||||
this.kubeClient = this.kubeConfig.makeApiClient(k8s.CoreV1Api);
|
this.kubeClient = this.kubeConfig.makeApiClient(k8s.CoreV1Api);
|
||||||
|
this.kubeClientApps = this.kubeConfig.makeApiClient(k8s.AppsV1Api);
|
||||||
this.kubeClientBatch = this.kubeConfig.makeApiClient(k8s.BatchV1Api);
|
this.kubeClientBatch = this.kubeConfig.makeApiClient(k8s.BatchV1Api);
|
||||||
this.rbacAuthorizationV1Api = this.kubeConfig.makeApiClient(k8s.RbacAuthorizationV1Api);
|
this.rbacAuthorizationV1Api = this.kubeConfig.makeApiClient(k8s.RbacAuthorizationV1Api);
|
||||||
this.namespace = 'default';
|
this.namespace = 'default';
|
||||||
|
@ -47,13 +51,17 @@ class Kubernetes implements ProviderInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
async PushLogUpdate(logs: string) {
|
async PushLogUpdate(logs: string) {
|
||||||
const body: k8s.V1ConfigMap = new k8s.V1ConfigMap();
|
// push logs to nginx file server via 'LOG_SERVICE_IP' env var
|
||||||
body.data = {};
|
const ip = process.env[`LOG_SERVICE_IP`];
|
||||||
body.data['logs'] = logs;
|
if (ip === undefined) {
|
||||||
body.metadata = { name: `${this.jobName}-logs`, namespace: this.namespace, labels: { app: 'unity-builder' } };
|
RemoteClientLogger.logWarning(`LOG_SERVICE_IP not set, skipping log push`);
|
||||||
RemoteClientLogger.log(`Pushing to Kubernetes ConfigMap`);
|
|
||||||
await this.kubeClient.createNamespacedConfigMap(this.namespace, body);
|
return;
|
||||||
RemoteClientLogger.log(`Pushed logs to Kubernetes ConfigMap`);
|
}
|
||||||
|
const url = `http://${ip}/api/log`;
|
||||||
|
RemoteClientLogger.log(`Pushing logs to ${url}`);
|
||||||
|
const response = await CloudRunnerSystem.Run(`curl -X POST -d "${logs}" ${url}`, false, true);
|
||||||
|
RemoteClientLogger.log(`Pushed logs to ${url} ${response}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async listResources(): Promise<ProviderResource[]> {
|
async listResources(): Promise<ProviderResource[]> {
|
||||||
|
@ -232,6 +240,7 @@ class Kubernetes implements ProviderInterface {
|
||||||
) {
|
) {
|
||||||
for (let index = 0; index < 3; index++) {
|
for (let index = 0; index < 3; index++) {
|
||||||
try {
|
try {
|
||||||
|
const ip = await KubernetesLogService.createLogDeployment(this.namespace, this.kubeClientApps, this.kubeClient);
|
||||||
const jobSpec = KubernetesJobSpecFactory.getJobSpec(
|
const jobSpec = KubernetesJobSpecFactory.getJobSpec(
|
||||||
commands,
|
commands,
|
||||||
image,
|
image,
|
||||||
|
@ -246,9 +255,12 @@ class Kubernetes implements ProviderInterface {
|
||||||
this.jobName,
|
this.jobName,
|
||||||
k8s,
|
k8s,
|
||||||
this.containerName,
|
this.containerName,
|
||||||
|
ip,
|
||||||
);
|
);
|
||||||
await new Promise((promise) => setTimeout(promise, 15000));
|
await new Promise((promise) => setTimeout(promise, 15000));
|
||||||
await KubernetesRole.createRole(this.serviceAccountName, this.namespace, this.rbacAuthorizationV1Api);
|
|
||||||
|
// await KubernetesRole.createRole(this.serviceAccountName, this.namespace, this.rbacAuthorizationV1Api);
|
||||||
|
|
||||||
const result = await this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
const result = await this.kubeClientBatch.createNamespacedJob(this.namespace, jobSpec);
|
||||||
CloudRunnerLogger.log(`Build job created`);
|
CloudRunnerLogger.log(`Build job created`);
|
||||||
await new Promise((promise) => setTimeout(promise, 5000));
|
await new Promise((promise) => setTimeout(promise, 5000));
|
||||||
|
|
|
@ -20,6 +20,7 @@ class KubernetesJobSpecFactory {
|
||||||
jobName: string,
|
jobName: string,
|
||||||
k8s: any,
|
k8s: any,
|
||||||
containerName: string,
|
containerName: string,
|
||||||
|
ip: string = '',
|
||||||
) {
|
) {
|
||||||
const job = new k8s.V1Job();
|
const job = new k8s.V1Job();
|
||||||
job.apiVersion = 'batch/v1';
|
job.apiVersion = 'batch/v1';
|
||||||
|
@ -81,6 +82,7 @@ class KubernetesJobSpecFactory {
|
||||||
|
|
||||||
return environmentVariable;
|
return environmentVariable;
|
||||||
}),
|
}),
|
||||||
|
{ name: 'LOG_SERVICE_IP', value: ip },
|
||||||
],
|
],
|
||||||
volumeMounts: [
|
volumeMounts: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
import { CoreV1Api } from '@kubernetes/client-node';
|
||||||
|
import * as k8s from '@kubernetes/client-node';
|
||||||
|
class KubernetesLogService {
|
||||||
|
// static async function, creates a deployment and service
|
||||||
|
static async createLogService(serviceAccountName: string, namespace: string, kubeClient: CoreV1Api) {
|
||||||
|
const serviceAccount = new k8s.V1ServiceAccount();
|
||||||
|
serviceAccount.apiVersion = 'v1';
|
||||||
|
serviceAccount.kind = 'ServiceAccount';
|
||||||
|
serviceAccount.metadata = {
|
||||||
|
name: serviceAccountName,
|
||||||
|
};
|
||||||
|
serviceAccount.automountServiceAccountToken = true;
|
||||||
|
|
||||||
|
return kubeClient.createNamespacedServiceAccount(namespace, serviceAccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async deleteLogService(serviceAccountName: string, namespace: string, kubeClient: CoreV1Api) {
|
||||||
|
await kubeClient.deleteNamespacedServiceAccount(serviceAccountName, namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async createLogDeployment(namespace: string, kubeClient: k8s.AppsV1Api, kubeClientCore: CoreV1Api) {
|
||||||
|
// json
|
||||||
|
/*
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
service: http-fileserver
|
||||||
|
name: http-fileserver
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy: {}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
service: http-fileserver
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: my-docker-hub-account/http-fileserver-kubernetes:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
name: http-fileserver
|
||||||
|
resources: {}
|
||||||
|
restartPolicy: Always
|
||||||
|
status: {}
|
||||||
|
*/
|
||||||
|
// create a deployment with above json
|
||||||
|
const deployment = new k8s.V1Deployment();
|
||||||
|
deployment.apiVersion = 'apps/v1';
|
||||||
|
deployment.kind = 'Deployment';
|
||||||
|
deployment.metadata = {
|
||||||
|
name: 'http-fileserver',
|
||||||
|
labels: {
|
||||||
|
service: 'http-fileserver',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
deployment.spec = {
|
||||||
|
selector: {
|
||||||
|
matchLabels: {
|
||||||
|
service: 'http-fileserver',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
replicas: 1,
|
||||||
|
strategy: {},
|
||||||
|
template: {
|
||||||
|
metadata: {
|
||||||
|
labels: {
|
||||||
|
service: 'http-fileserver',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
spec: {
|
||||||
|
containers: [
|
||||||
|
{
|
||||||
|
image: 'my-docker-hub-account/http-fileserver-kubernetes:latest',
|
||||||
|
imagePullPolicy: 'Always',
|
||||||
|
name: 'http-fileserver',
|
||||||
|
resources: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
restartPolicy: 'Always',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
await kubeClient.createNamespacedDeployment(namespace, deployment);
|
||||||
|
await this.createLogServiceExpose(namespace, kubeClientCore);
|
||||||
|
|
||||||
|
// wait in loop until serivce ip address is exposed
|
||||||
|
|
||||||
|
for (let index = 0; index < 10; index++) {
|
||||||
|
// wait for service to share ip address
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 10000));
|
||||||
|
|
||||||
|
// get ip address of service
|
||||||
|
const service = await kubeClientCore.readNamespacedService('http-fileserver', namespace);
|
||||||
|
const ip = service.body.status?.loadBalancer?.ingress?.[0]?.ip;
|
||||||
|
if (ip) {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create kubernetes service to expose deployment
|
||||||
|
static async createLogServiceExpose(namespace: string, kubeClient: CoreV1Api) {
|
||||||
|
// json
|
||||||
|
/*
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
labels:
|
||||||
|
service: http-fileserver
|
||||||
|
name: http-fileserver
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: 80-80
|
||||||
|
port: 80
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 80
|
||||||
|
selector:
|
||||||
|
service: http-fileserver
|
||||||
|
type: LoadBalancer
|
||||||
|
status:
|
||||||
|
loadBalancer: {}
|
||||||
|
*/
|
||||||
|
// create a service with above json
|
||||||
|
const service = new k8s.V1Service();
|
||||||
|
service.apiVersion = 'v1';
|
||||||
|
service.kind = 'Service';
|
||||||
|
service.metadata = {
|
||||||
|
name: 'http-fileserver',
|
||||||
|
labels: {
|
||||||
|
service: 'http-fileserver',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
service.spec = {
|
||||||
|
ports: [
|
||||||
|
{
|
||||||
|
name: '80-80',
|
||||||
|
port: 80,
|
||||||
|
protocol: 'TCP',
|
||||||
|
targetPort: 80,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selector: {
|
||||||
|
service: 'http-fileserver',
|
||||||
|
},
|
||||||
|
type: 'LoadBalancer',
|
||||||
|
};
|
||||||
|
await kubeClient.createNamespacedService(namespace, service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default KubernetesLogService;
|
|
@ -39,6 +39,7 @@ export class RemoteClientLogger {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CloudRunnerLogger.log(`Collected Logs`);
|
CloudRunnerLogger.log(`Collected Logs`);
|
||||||
|
CloudRunnerLogger.log(process.env[`LOG_SERVICE_IP`] || ``);
|
||||||
const logs = fs.readFileSync(RemoteClientLogger.LogFilePath).toString();
|
const logs = fs.readFileSync(RemoteClientLogger.LogFilePath).toString();
|
||||||
CloudRunnerLogger.log(logs);
|
CloudRunnerLogger.log(logs);
|
||||||
await Kubernetes.Instance.PushLogUpdate(logs);
|
await Kubernetes.Instance.PushLogUpdate(logs);
|
||||||
|
|
Loading…
Reference in New Issue