feat: k8s operator

This commit is contained in:
2025-05-12 12:35:11 +07:00
parent cffe651d6f
commit 952928ffcb
19 changed files with 2486 additions and 0 deletions
+169
View File
@@ -0,0 +1,169 @@
import { NAMESPACE } from '../config/constants';
/**
* Namespace definition
*/
export const minikuraNamespace = {
apiVersion: 'v1',
kind: 'Namespace',
metadata: {
name: NAMESPACE,
},
};
/**
* Service account
*/
export const minikuraServiceAccount = {
apiVersion: 'v1',
kind: 'ServiceAccount',
metadata: {
name: 'minikura-operator',
namespace: NAMESPACE,
},
};
/**
* Cluster role
*/
export const minikuraClusterRole = {
apiVersion: 'rbac.authorization.k8s.io/v1',
kind: 'ClusterRole',
metadata: {
name: 'minikura-operator-role',
},
rules: [
{
apiGroups: [''],
resources: ['configmaps', 'services', 'secrets'],
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'],
},
{
apiGroups: ['apps'],
resources: ['deployments', 'statefulsets'],
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'],
},
{
apiGroups: ['networking.k8s.io'],
resources: ['ingresses'],
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'],
},
{
apiGroups: ['apiextensions.k8s.io'],
resources: ['customresourcedefinitions'],
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'],
},
{
apiGroups: ['minikura.kirameki.cafe'],
resources: ['minecraftservers', 'velocityproxies'],
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete'],
},
{
apiGroups: ['minikura.kirameki.cafe'],
resources: ['minecraftservers/status', 'velocityproxies/status'],
verbs: ['get', 'update', 'patch'],
},
],
};
/**
* Cluster role binding
*/
export const minikuraClusterRoleBinding = {
apiVersion: 'rbac.authorization.k8s.io/v1',
kind: 'ClusterRoleBinding',
metadata: {
name: 'minikura-operator-role-binding',
},
subjects: [
{
kind: 'ServiceAccount',
name: 'minikura-operator',
namespace: NAMESPACE,
},
],
roleRef: {
kind: 'ClusterRole',
name: 'minikura-operator-role',
apiGroup: 'rbac.authorization.k8s.io',
},
};
/**
* Deployment for the Minikura operator
*/
export const minikuraOperatorDeployment = {
apiVersion: 'apps/v1',
kind: 'Deployment',
metadata: {
name: 'minikura-operator',
namespace: NAMESPACE,
},
spec: {
replicas: 1,
selector: {
matchLabels: {
app: 'minikura-operator',
},
},
template: {
metadata: {
labels: {
app: 'minikura-operator',
},
},
spec: {
serviceAccountName: 'minikura-operator',
containers: [
{
name: 'operator',
image: '${REGISTRY_URL}/minikura-operator:latest',
env: [
{
name: 'DATABASE_URL',
valueFrom: {
secretKeyRef: {
name: 'minikura-operator-secrets',
key: 'DATABASE_URL',
},
},
},
{
name: 'KUBERNETES_NAMESPACE',
value: NAMESPACE,
},
{
name: 'USE_CRDS',
value: 'true',
},
],
resources: {
requests: {
memory: '256Mi',
cpu: '200m',
},
limits: {
memory: '512Mi',
cpu: '500m',
},
},
livenessProbe: {
exec: {
command: ['bun', '-e', "console.log('Health check')"],
},
initialDelaySeconds: 30,
periodSeconds: 30,
},
readinessProbe: {
exec: {
command: ['bun', '-e', "console.log('Ready check')"],
},
initialDelaySeconds: 5,
periodSeconds: 10,
},
},
],
},
},
},
};
@@ -0,0 +1,156 @@
import { API_GROUP, API_VERSION, RESOURCE_TYPES } from '../config/constants';
export const REVERSE_PROXY_SERVER_CRD = {
apiVersion: 'apiextensions.k8s.io/v1',
kind: 'CustomResourceDefinition',
metadata: {
name: `${RESOURCE_TYPES.REVERSE_PROXY_SERVER.plural}.${API_GROUP}`,
},
spec: {
group: API_GROUP,
versions: [
{
name: API_VERSION,
served: true,
storage: true,
schema: {
openAPIV3Schema: {
type: 'object',
properties: {
spec: {
type: 'object',
required: ['id', 'external_address', 'external_port'],
properties: {
id: {
type: 'string',
pattern: '^[a-zA-Z0-9-_]+$',
description: 'ID of the reverse proxy server',
},
description: {
type: 'string',
nullable: true,
description: 'Optional description of the server',
},
external_address: {
type: 'string',
description: 'External address of the proxy server',
},
external_port: {
type: 'integer',
minimum: 1,
maximum: 65535,
description: 'External port of the proxy server',
},
listen_port: {
type: 'integer',
minimum: 1,
maximum: 65535,
default: 25565,
nullable: true,
description: 'Port the proxy server listens on internally',
},
type: {
type: 'string',
enum: ['VELOCITY', 'BUNGEECORD'],
default: 'VELOCITY',
nullable: true,
description: 'Type of the reverse proxy server',
},
memory: {
type: 'string',
default: '512M',
nullable: true,
description: 'Memory allocation for the server',
},
environmentVariables: {
type: 'array',
nullable: true,
items: {
type: 'object',
required: ['key', 'value'],
properties: {
key: {
type: 'string',
description: 'Environment variable key',
},
value: {
type: 'string',
description: 'Environment variable value',
},
},
},
},
},
},
status: {
type: 'object',
nullable: true,
properties: {
phase: {
type: 'string',
enum: ['Pending', 'Running', 'Failed'],
description: 'Current phase of the server',
},
message: {
type: 'string',
nullable: true,
description: 'Detailed message about the current status',
},
apiKey: {
type: 'string',
nullable: true,
description: 'API key for server communication',
},
internalId: {
type: 'string',
nullable: true,
description: 'Internal ID assigned by Minikura',
},
lastSyncedAt: {
type: 'string',
nullable: true,
description: 'Last time the server was synced with Kubernetes',
},
},
},
},
},
},
additionalPrinterColumns: [
{
name: 'Type',
type: 'string',
jsonPath: '.spec.type',
},
{
name: 'External Address',
type: 'string',
jsonPath: '.spec.external_address',
},
{
name: 'External Port',
type: 'integer',
jsonPath: '.spec.external_port',
},
{
name: 'Status',
type: 'string',
jsonPath: '.status.phase',
},
{
name: 'Age',
type: 'date',
jsonPath: '.metadata.creationTimestamp',
},
],
},
],
scope: 'Namespaced',
names: {
singular: RESOURCE_TYPES.REVERSE_PROXY_SERVER.singular,
plural: RESOURCE_TYPES.REVERSE_PROXY_SERVER.plural,
kind: RESOURCE_TYPES.REVERSE_PROXY_SERVER.kind,
shortNames: RESOURCE_TYPES.REVERSE_PROXY_SERVER.shortNames,
},
},
};
+132
View File
@@ -0,0 +1,132 @@
import { API_GROUP, API_VERSION, RESOURCE_TYPES } from '../config/constants';
export const MINECRAFT_SERVER_CRD = {
apiVersion: 'apiextensions.k8s.io/v1',
kind: 'CustomResourceDefinition',
metadata: {
name: `${RESOURCE_TYPES.MINECRAFT_SERVER.plural}.${API_GROUP}`,
},
spec: {
group: API_GROUP,
versions: [
{
name: API_VERSION,
served: true,
storage: true,
schema: {
openAPIV3Schema: {
type: 'object',
properties: {
spec: {
type: 'object',
required: ['id', 'type', 'listen_port'],
properties: {
id: {
type: 'string',
pattern: '^[a-zA-Z0-9-_]+$',
description: 'ID of the Minecraft server',
},
description: {
type: 'string',
nullable: true,
description: 'Optional description of the server',
},
listen_port: {
type: 'integer',
minimum: 1,
maximum: 65535,
description: 'Port the server listens on',
},
type: {
type: 'string',
enum: ['STATEFUL', 'STATELESS'],
description: 'Type of the server',
},
memory: {
type: 'string',
nullable: true,
default: '1G',
description: 'Memory allocation for the server',
},
environmentVariables: {
type: 'array',
nullable: true,
items: {
type: 'object',
required: ['key', 'value'],
properties: {
key: {
type: 'string',
description: 'Environment variable key',
},
value: {
type: 'string',
description: 'Environment variable value',
},
},
},
},
},
},
status: {
type: 'object',
nullable: true,
properties: {
phase: {
type: 'string',
enum: ['Pending', 'Running', 'Failed'],
description: 'Current phase of the server',
},
message: {
type: 'string',
nullable: true,
description: 'Detailed message about the current status',
},
apiKey: {
type: 'string',
nullable: true,
description: 'API key for server communication',
},
internalId: {
type: 'string',
nullable: true,
description: 'Internal ID assigned by Minikura',
},
lastSyncedAt: {
type: 'string',
nullable: true,
description: 'Last time the server was synced with Kubernetes',
},
},
},
},
},
},
additionalPrinterColumns: [
{
name: 'Type',
type: 'string',
jsonPath: '.spec.type',
},
{
name: 'Status',
type: 'string',
jsonPath: '.status.phase',
},
{
name: 'Age',
type: 'date',
jsonPath: '.metadata.creationTimestamp',
},
],
},
],
scope: 'Namespaced',
names: {
singular: RESOURCE_TYPES.MINECRAFT_SERVER.singular,
plural: RESOURCE_TYPES.MINECRAFT_SERVER.plural,
kind: RESOURCE_TYPES.MINECRAFT_SERVER.kind,
shortNames: RESOURCE_TYPES.MINECRAFT_SERVER.shortNames,
},
},
};