Skip to content

Commit 88ffd36

Browse files
committed
Add the k8s files
0 parents  commit 88ffd36

12 files changed

+640
-0
lines changed

kafka_service.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: kafka
5+
spec:
6+
ports:
7+
- name: plaintext
8+
targetPort: plaintext
9+
port: 9092
10+
- name: controller
11+
targetPort: controller
12+
port: 9093
13+
selector:
14+
microstream.one/cluster-component: kafka

kafka_statefulset.yaml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
apiVersion: apps/v1
2+
kind: StatefulSet
3+
metadata:
4+
name: kafka
5+
spec:
6+
serviceName: kafka
7+
replicas: 1
8+
podManagementPolicy: Parallel
9+
selector:
10+
matchLabels:
11+
microstream.one/cluster-component: kafka
12+
template:
13+
metadata:
14+
labels:
15+
microstream.one/cluster-component: kafka
16+
spec:
17+
imagePullSecrets: [ name: microstream-ocir-credentials ]
18+
containers:
19+
- name: kafka
20+
image: ocir.microstream.one/onprem/image/microstream-cluster-kafka:1.10.0-SNAPSHOT
21+
ports:
22+
- name: plaintext
23+
containerPort: 9092
24+
- name: controller
25+
containerPort: 9093
26+
env:
27+
# Configurations are automatically parsed from envars prefixed with KAFKA_CFG
28+
# The keys are transformed from snake case to dotted lowercase
29+
30+
# Used for kafka node id and ADVERTISED_LISTENER generation. The bootstrap script takes the id part (for kafka-0 it would be 0)
31+
# and sets the NODE_ID to that value. For ADVERTISED_LISTENER it will simply replace %'s with the pod name
32+
# e.g. CLIENT://%.kafka:9092 = CLIENT://kafka-0.kafka:9092
33+
- name: MY_POD_NAME
34+
valueFrom:
35+
fieldRef:
36+
fieldPath: metadata.name
37+
38+
# UUID identifying this kafka cluster
39+
- name: KAFKA_CFG_CLUSTER_ID
40+
value: sZDP3FUBQGWfNSEFG1Y-jA
41+
42+
# Server Basics
43+
- name: KAFKA_CFG_PROCESS_ROLES
44+
value: broker,controller
45+
46+
- name: KAFKA_CFG_CONTROLLER_QUORUM_BOOTSTRAP_SERVERS
47+
value: localhost:9093
48+
49+
# Server Socket Settings
50+
- name: KAFKA_CFG_INTER_BROKER_LISTENER_NAME
51+
value: PLAINTEXT
52+
53+
- name: KAFKA_CFG_CONTROLLER_LISTENER_NAMES
54+
value: CONTROLLER
55+
56+
- name: KAFKA_CFG_LISTENERS
57+
value: PLAINTEXT://:9092,CONTROLLER://:9093
58+
59+
- name: ADVERTISED_LISTENERS_TEMPLATE
60+
value: PLAINTEXT://%.kafka:9092,CONTROLLER://%.kafka:9093
61+
62+
- name: KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP
63+
value: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL
64+
65+
# Should be set appropriately with how many cores are available for multithreading etc.
66+
- name: KAFKA_CFG_NUM_NETWORK_THREADS
67+
value: "3"
68+
# Should be set appropriately with how many cores are available for multithreading etc.
69+
- name: KAFKA_CFG_NUM_IO_THREADS
70+
value: "8"
71+
72+
# Log Basics
73+
- name: KAFKA_CFG_LOG_DIR
74+
value: /mnt/kafka/logs
75+
76+
- name: KAFKA_CFG_NUM_PARTITIONS
77+
value: "1"
78+
79+
# Internal Topic Settings
80+
- name: KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR
81+
value: "1"
82+
83+
- name: KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR
84+
value: "1"
85+
86+
- name: KAFKA_LOG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR
87+
value: "1"
88+
89+
- name: KAFKA_CFG_CONFIG_STORAGE_REPLICATION_FACTOR
90+
value: "1"
91+
92+
- name: KAFKA_CFG_OFFSET_STORAGE_REPLICATION_FACTOR
93+
value: "1"
94+
95+
- name: KAFKA_CFG_STATUS_STORAGE_REPLICATION_FACTOR
96+
value: "1"
97+
98+
- name: KAFKA_CFG_ERRORS_DEADLETTERQUEUE_TOPIC_REPLICATION_FACTOR
99+
value: "1"
100+
101+
- name: KAFKA_CFG_REPLICATION_FACTOR
102+
value: "1"
103+
104+
# Log Retention Policy
105+
# These need to be kept until we are sure that the masternode has consumed the messages
106+
# because new storage nodes will clone the masternode storage, we effectively don't need messages older than the
107+
# current masternode state.
108+
- name: KAFKA_CFG_LOG_RETENTION_HOURS
109+
# 336 hours = 2 weeks
110+
value: "336"
111+
112+
volumeMounts:
113+
- name: logs
114+
mountPath: /mnt/kafka
115+
volumeClaimTemplates:
116+
- metadata:
117+
name: logs
118+
spec:
119+
accessModes: [ ReadWriteOnce ]
120+
resources:
121+
requests:
122+
storage: 20G

masternode_pod.yaml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: masternode
5+
spec:
6+
imagePullSecrets: [ name: microstream-ocir-credentials ]
7+
securityContext:
8+
runAsNonRoot: true
9+
fsGroupChangePolicy: OnRootMismatch
10+
fsGroup: 10000
11+
runAsUser: 10000
12+
runAsGroup: 10000
13+
initContainers:
14+
- name: prepare-masternode
15+
image: curlimages/curl:8.11.1
16+
command:
17+
- sh
18+
- -ce
19+
- |
20+
# Wait for the user rest service project to exist
21+
# You can upload the jar like this:
22+
# `kubectl cp -c prepare-masternode /path/to/jar masternode:/storage/project/project.jar`
23+
# If you have a libs folder as well you can copy it with
24+
# `kubectl cp -c prepare-masternode /path/to/libs masternode:/storage/project`
25+
# When you are done create the ready flag with
26+
# `kubectl exec -ti -c prepare-masternode pod/masternode -- touch /storage/project/ready`
27+
mkdir -p /storage/project
28+
echo "Waiting for user rest service jar (timeout=10min)..."
29+
i=0
30+
until [ -f /storage/project/ready ]; do
31+
sleep 1s
32+
# Fail if we time out
33+
if [ $i -gt 600 ]; then
34+
echo "Timed out waiting for /storage/project/ready to exist" >&2
35+
exit 1
36+
fi
37+
i=$((i+1))
38+
done
39+
echo "Success!"
40+
41+
# Check for kafka ready flag for 5 minutes
42+
echo "Waiting for kafka to be ready (timeout=5min)..."
43+
i=0
44+
until nc -z -w5 kafka 9092; do
45+
sleep 1s
46+
# Fail if we time out
47+
if [ $i -gt 300 ]; then
48+
echo "Timed out waiting for kafka to be ready" >&2
49+
exit 1
50+
fi
51+
i=$((i+1))
52+
done
53+
echo "Success!"
54+
securityContext:
55+
allowPrivilegeEscalation: false
56+
capabilities:
57+
drop: [ all ]
58+
volumeMounts:
59+
- name: storage
60+
mountPath: /storage
61+
containers:
62+
- name: masternode
63+
image: ocir.microstream.one/onprem/image/microstream-cluster-storage-node:1.10.0-SNAPSHOT
64+
workingDir: /storage
65+
args: [ "/storage/project/project.jar" ]
66+
env:
67+
- name: MSCNL_PROD_MODE
68+
value: "true"
69+
- name: KAFKA_BOOTSTRAP_SERVERS
70+
value: kafka-0.kafka:9092
71+
- name: MSCNL_KAFKA_TOPIC_NAME
72+
value: storage-data
73+
- name: MSCNL_SECURE_KAFKA
74+
value: "false"
75+
- name: MSCNL_KAFKA_USERNAME
76+
value: ""
77+
- name: MSCNL_KAFKA_PASSWORD
78+
value: ""
79+
# Keep Spring Boot (if used in the user rest service) from initializing the user controllers which might lead to NPEs
80+
- name: SPRING_MAIN_LAZY-INITIALIZATION
81+
value: "true"
82+
- name: IS_BACKUP_NODE
83+
value: "true"
84+
- name: BACKUP_PROXY_SERVICE_URL
85+
value: external-resource-proxy
86+
ports:
87+
- name: http
88+
containerPort: 8080
89+
# Restart the pod if container is not responsive at all
90+
livenessProbe:
91+
timeoutSeconds: 5
92+
failureThreshold: 5
93+
httpGet:
94+
path: /microstream-cluster-controller/microstream-health
95+
port: http
96+
# Remove the pod from being ready if we fail to check
97+
readinessProbe:
98+
timeoutSeconds: 4
99+
failureThreshold: 3
100+
httpGet:
101+
path: /microstream-cluster-controller/microstream-health/ready
102+
port: http
103+
# Give the container ~50 seconds to fully start up
104+
startupProbe:
105+
timeoutSeconds: 5
106+
failureThreshold: 10
107+
httpGet:
108+
path: /microstream-cluster-controller/microstream-health
109+
port: http
110+
securityContext:
111+
allowPrivilegeEscalation: false
112+
capabilities:
113+
drop: [ all ]
114+
volumeMounts:
115+
- name: storage
116+
mountPath: /storage
117+
volumes:
118+
- name: storage
119+
persistentVolumeClaim:
120+
claimName: masternode-storage

masternode_pvclaim.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: v1
2+
kind: PersistentVolumeClaim
3+
metadata:
4+
name: masternode-storage
5+
spec:
6+
# Needs to be read-write-many so every storage node can attach and clone the storage as a starting point
7+
accessModes: [ ReadWriteMany ]
8+
resources:
9+
requests:
10+
storage: 20G

proxy_configmap.yaml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: proxy
5+
data:
6+
nginx.conf: |
7+
# Automatically figure out how many workers (threads) should be started based on the available cpu cores
8+
worker_processes auto;
9+
10+
events {
11+
# The maximum number of simultaneous connections that can be opened by a worker process.
12+
# Check allowed open file limits per process with: `ulimit -n`
13+
# Most distros have a default limit of 1k
14+
worker_connections 1000;
15+
}
16+
17+
http {
18+
# Disable access log to prevent spam
19+
access_log off;
20+
21+
# Filter out HTTP 200-300 access logs. Keep others like HTTP 400 (user error) HTTP 500 (server error)
22+
map $status $loggable {
23+
~^[23] 0;
24+
default 1;
25+
}
26+
27+
proxy_http_version 1.1;
28+
# The dns resolver inside the kubernetes cluster. If we don't add this nginx won't know how to resolve our subdomains like 'writerproxy'
29+
resolver kube-dns.kube-system.svc.cluster.local;
30+
31+
# Map PUT|PATH|DELETE|POST requests to the writerproxy domain
32+
# Any modifying request that the cluster receives should go through the writerproxy
33+
# This node knows which storage node is the current writer and forwards the request to it
34+
map $request_method $upstream_location {
35+
PUT writerproxy.my-microstream-cluster.svc.cluster.local;
36+
PATCH writerproxy.my-microstream-cluster.svc.cluster.local;
37+
DELETE writerproxy.my-microstream-cluster.svc.cluster.local;
38+
POST writerproxy.my-microstream-cluster.svc.cluster.local;
39+
40+
# Any other request can go to the node subdomain. This will go to a random storage node that the loadbalancer deems as sufficent.
41+
default storagenode.my-microstream-cluster.svc.cluster.local;
42+
}
43+
44+
server {
45+
# Listen for incoming connections on port 8080. The proxy service resource specifies which port you actually have to call, but
46+
# a good practise is to use 8080 inside the containers so we don't need to access the lower port number range
47+
listen 8080;
48+
49+
location / {
50+
# Set some proxy header information
51+
proxy_set_header Host $proxy_host;
52+
proxy_set_header Connection close;
53+
# Select the correct subdomain and forward the request to it.
54+
# Internally the cluster communicates via http. All the https traffic should come from the outside to a configured ingress
55+
proxy_pass http://$upstream_location;
56+
}
57+
}
58+
}

proxy_deployment.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: proxy
5+
spec:
6+
replicas: 1
7+
selector:
8+
matchLabels:
9+
microstream.one/cluster-component: proxy
10+
template:
11+
metadata:
12+
labels:
13+
microstream.one/cluster-component: proxy
14+
spec:
15+
imagePullSecrets: [ name: microstream-ocir-credentials ]
16+
containers:
17+
- name: nginx
18+
image: nginx:1.27-alpine
19+
ports:
20+
- containerPort: 8080
21+
name: http
22+
protocol: TCP
23+
volumeMounts:
24+
- name: config
25+
subPath: nginx.conf
26+
mountPath: /etc/nginx/nginx.conf
27+
volumes:
28+
- name: config
29+
configMap:
30+
name: proxy
31+

proxy_service.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: proxy
5+
spec:
6+
selector:
7+
microstream.one/cluster-component: proxy
8+
ports:
9+
- name: http
10+
port: 80
11+
targetPort: http

0 commit comments

Comments
 (0)