Skip to content

Commit 72c6c87

Browse files
authored
Translate NodeStatus into taint in order to fitting libscheduler (#192)
* fix error in libscheduler Signed-off-by: ichAB <[email protected]> * update readme Signed-off-by: ichAB <[email protected]> * translate Nodestatus to taint Signed-off-by: ichAB <[email protected]> * fmt Signed-off-by: ichAB <[email protected]> * modify readme Signed-off-by: ichAB <[email protected]> * fix clippy Signed-off-by: ichAB <[email protected]> --------- Signed-off-by: ichAB <[email protected]>
1 parent 77b6b44 commit 72c6c87

File tree

20 files changed

+501
-252
lines changed

20 files changed

+501
-252
lines changed

README.md

Lines changed: 20 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# rk8s - A Lite Version of Kubernetes in Rust
32

43
rk8s is a lightweight, Kubernetes-compatible container orchestration system built on top of [Youki](https://github.com/youki-dev/youki), implementing the Container Runtime Interface (CRI) with support for three primary workload types: single containers, Kubernetes-style pods, and Docker Compose-style multi-container applications.
@@ -180,85 +179,44 @@ sudo mv target/debug/libbridge /opt/cni/bin/
180179
mkdir -p rootfs
181180
docker export $(docker create busybox) | tar -C rootfs -xvf -
182181
```
183-
4. **Start Xline:**
184-
```bash
185-
git clone https://github.com/xline-kv/Xline.git
186-
cd Xline
187-
docker pull ghcr.io/xline-kv/xline:latest
188-
cp fixtures/{private,public}.pem scripts/
189-
./scripts/quick_start.sh
190-
```
191182
### Usage Examples
192-
193183
**Single Container:**
194184
```bash
195-
sudo rkl container run single.yaml
196-
sudo rkl container list
197-
sudo rkl container exec single-container-test /bin/sh
185+
sudo project/target/debug/rkl container run single.yaml
186+
sudo project/target/debug/rkl container list
187+
sudo project/target/debug/rkl container exec single-container-test /bin/sh
198188
```
199-
200189
**Pod Management(Standalone):**
190+
201191
```bash
202-
sudo rkl pod run pod.yaml
203-
sudo rkl pod state simple-container-task
204-
sudo rkl pod exec simple-container-task container-name /bin/sh
192+
sudo project/target/debug/rkl pod run pod.yaml
193+
sudo project/target/debug/rkl pod state simple-container-task
194+
sudo project/target/debug/rkl pod exec simple-container-task container-name /bin/sh
205195
```
196+
206197
**Pod Management(Cluster):**
207198
```bash
208-
# Create pod via RKS control plane
209-
sudo rkl pod create pod.yaml --cluster 127.0.0.1:50051
210-
211-
# List pods from RKS
212-
RKS_ADDRESS=127.0.0.1:50051 sudo rkl pod list
213-
214-
# Delete pod via RKS
215-
sudo rkl pod delete simple-container-task --cluster 127.0.0.1:50051
199+
# Create pod via RKS control plane
200+
sudo project/target/debug/rkl pod create pod.yaml --cluster 127.0.0.1:50051
201+
# List pods from RKS
202+
sudo project/target/debug/rkl pod list --cluster 127.0.0.1:50051
203+
# Delete pod via RKS
204+
sudo project/target/debug/rkl pod delete simple-container-task --cluster 127.0.0.1:50051
216205
```
217206

218207
**Compose Applications:**
219208
```bash
220-
sudo rkl compose up
221-
sudo rkl compose ps
222-
sudo rkl compose down
209+
sudo project/target/debug/rkl compose up
210+
sudo project/target/debug/rkl compose ps
211+
sudo project/target/debug/rkl compose down
223212
```
224213

225214
**Daemon Mode:**
226215
```bash
227-
export RKL_ADDRESS=127.0.0.1:50051
228-
sudo rkl pod daemon # Monitors /etc/rk8s/manifests/ and acts as work node of rks
229-
```
230-
**Start RKS:**
231-
```bash
232-
sudo rks start --config config.yaml
233-
```
234-
Example config.yaml:
235-
```yaml
236-
addr: "127.0.0.1:50051"
237-
238-
xline_config:
239-
240-
endpoints:
241-
242-
- "http://172.20.0.3:2379"
243-
244-
- "http://172.20.0.4:2379"
245-
246-
- "http://172.20.0.5:2379"
247-
248-
prefix: "/coreos.com/network"
249-
250-
subnet_lease_renew_margin: 60
251-
252-
network_config:
253-
254-
Network: "10.1.0.0/16"
255-
256-
SubnetMin: "10.1.1.0"
257-
258-
SubnetMax: "10.1.254.0"
259-
260-
SubnetLen: 24
216+
sudo RKL_ADDRESS=127.0.0.1:50051 project/target/debug/rkl pod daemon # Monitors /etc/rk8s/manifests/ and acts as work node of rks
261217
```
218+
**RKS:**
219+
For detail about building a cluster with RKS and RKL, please refer to [RKS–RKL usage](./project/rks/readme.md).
262220
## Key Features
263221

264222
- **CRI Compliance** - Full Container Runtime Interface implementation

project/common/src/lib.rs

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ pub struct PodSpec {
3838
pub containers: Vec<ContainerSpec>,
3939
#[serde(default)]
4040
pub init_containers: Vec<ContainerSpec>,
41+
#[serde(default)]
42+
pub tolerations: Vec<Toleration>,
4143
}
4244

4345
#[derive(Debug, Serialize, Deserialize, Clone)]
@@ -95,6 +97,66 @@ pub struct PodStatus {
9597
#[serde(rename = "podIP")]
9698
pub pod_ip: Option<String>,
9799
}
100+
101+
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
102+
pub struct Toleration {
103+
/// Empty means match all taint keys.
104+
pub key: Option<TaintKey>,
105+
106+
/// Operator represents a key's relationship to the value.
107+
#[serde(default)]
108+
pub operator: TolerationOperator,
109+
110+
/// Effect indicates the taint effect to match. None means match all.
111+
pub effect: Option<TaintEffect>,
112+
113+
#[serde(default)]
114+
pub value: String,
115+
}
116+
impl Toleration {
117+
pub fn tolerate(&self, taint: &Taint) -> bool {
118+
if self.effect.is_some() && self.effect.as_ref().unwrap() != &taint.effect {
119+
return false;
120+
}
121+
if self.key.is_some() && self.key.as_ref().unwrap() != &taint.key {
122+
return false;
123+
}
124+
match self.operator {
125+
TolerationOperator::Equal => self.value == taint.value,
126+
TolerationOperator::Exists => true,
127+
}
128+
}
129+
}
130+
#[derive(Debug, Serialize, Deserialize, Clone)]
131+
pub enum TolerationOperator {
132+
Exists,
133+
Equal,
134+
}
135+
136+
impl Default for TolerationOperator {
137+
fn default() -> Self {
138+
Self::Equal
139+
}
140+
}
141+
142+
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
143+
pub enum TaintEffect {
144+
NoSchedule,
145+
PreferNoSchedule,
146+
NoExecute,
147+
}
148+
149+
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
150+
pub enum TaintKey {
151+
NodeNotReady,
152+
NodeUnreachable,
153+
NodeUnschedulable,
154+
NodeMemoryPressure,
155+
NodeDiskPressure,
156+
NodeNetworkUnavailable,
157+
NodeOutOfService,
158+
}
159+
98160
#[derive(Debug, Serialize, Deserialize, Clone)]
99161
pub enum RksMessage {
100162
//request
@@ -107,7 +169,7 @@ pub enum RksMessage {
107169
UserRequest(String),
108170
Heartbeat {
109171
node_name: String,
110-
conditions: Vec<NodeCondition>,
172+
status: NodeStatus,
111173
},
112174
SetNetwork(Box<NodeNetworkConfig>),
113175
UpdateRoutes(String, Vec<Route>),
@@ -126,8 +188,25 @@ pub enum RksMessage {
126188
pub struct NodeSpec {
127189
#[serde(rename = "podCIDR")]
128190
pub pod_cidr: String, // Pod network CIDR assigned to this node
191+
#[serde(default)]
192+
pub taints: Vec<Taint>,
193+
}
194+
#[derive(Debug, Serialize, Deserialize, Clone)]
195+
pub struct Taint {
196+
pub key: TaintKey,
197+
#[serde(default)]
198+
pub value: String,
199+
pub effect: TaintEffect,
200+
}
201+
impl Taint {
202+
pub fn new(key: TaintKey, effect: TaintEffect) -> Self {
203+
Self {
204+
key,
205+
effect,
206+
value: String::new(),
207+
}
208+
}
129209
}
130-
131210
/// Node status
132211
#[derive(Debug, Serialize, Deserialize, Clone)]
133212
pub struct NodeStatus {

project/libscheduler/src/cache.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,14 @@ impl Cache {
4646
} else {
4747
return false;
4848
};
49+
4950
pod_info.scheduled = Some(node_name.to_owned());
5051
node.requested.cpu += pod_info.spec.resources.cpu;
5152
node.requested.memory += pod_info.spec.resources.memory;
53+
5254
true
5355
}
5456

55-
/// Un assume a pod, if the pod is not scheduled, do nothing.
5657
pub fn unassume(&mut self, pod_name: &str) -> Option<PodInfo> {
5758
let pod_info = self.pods.get_mut(pod_name)?;
5859
let node_name_opt = pod_info.scheduled.clone();
@@ -61,9 +62,11 @@ impl Cache {
6162
} else {
6263
return None;
6364
};
65+
6466
pod_info.scheduled = None;
6567
node.requested.cpu -= pod_info.spec.resources.cpu;
6668
node.requested.memory -= pod_info.spec.resources.memory;
69+
6770
Some(pod_info.clone())
6871
}
6972

@@ -74,16 +77,28 @@ impl Cache {
7477
pub fn remove_pod(&mut self, pod_name: &str) -> Option<PodInfo> {
7578
if let Some(p) = self.pods.get(pod_name)
7679
&& let Some(n) = &p.scheduled
80+
&& let Some(node) = self.nodes.get_mut(n)
7781
{
78-
let node = self.nodes.get_mut(n);
79-
if let Some(node) = node {
80-
node.requested.cpu -= p.spec.resources.cpu;
81-
node.requested.memory -= p.spec.resources.memory;
82-
}
82+
node.requested.cpu -= p.spec.resources.cpu;
83+
node.requested.memory -= p.spec.resources.memory;
8384
}
8485
self.pods.remove(pod_name)
8586
}
8687

88+
pub fn update_node(&mut self, new_node: NodeInfo) -> Option<NodeInfo> {
89+
let name = new_node.name.clone();
90+
if let Some(old_node) = self.nodes.get_mut(&name) {
91+
let requested = old_node.requested.clone();
92+
old_node.labels = new_node.labels;
93+
old_node.spec = new_node.spec;
94+
old_node.allocatable = new_node.allocatable;
95+
old_node.requested = requested;
96+
Some(old_node.clone())
97+
} else {
98+
self.nodes.insert(name.clone(), new_node)
99+
}
100+
}
101+
87102
pub fn pop_pod_on_node(&mut self, node_name: &str) -> Vec<PodNameWithPriority> {
88103
let mut res = Vec::new();
89104
self.pods
@@ -97,10 +112,6 @@ impl Cache {
97112
res
98113
}
99114

100-
pub fn update_node(&mut self, node: NodeInfo) -> Option<NodeInfo> {
101-
self.nodes.insert(node.name.clone(), node)
102-
}
103-
104115
pub fn remove_node(&mut self, node_name: &str) {
105116
self.nodes.remove(node_name);
106117
}

project/libscheduler/src/models.rs

Lines changed: 1 addition & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::{cmp::Ordering, collections::HashMap};
22

33
use tokio::time::Instant;
44

5+
use common::*;
56
#[derive(Clone, Default, Debug)]
67
pub struct ResourcesRequirements {
78
/// CPU resource limits, measured in millicores.
@@ -196,7 +197,6 @@ pub struct PodInfo {
196197
pub queued_info: QueuedInfo,
197198
pub scheduled: Option<String>,
198199
}
199-
200200
impl PartialEq for PodInfo {
201201
fn eq(&self, other: &Self) -> bool {
202202
self.spec.priority == other.spec.priority
@@ -264,81 +264,3 @@ pub struct Assignment {
264264
pub pod_name: String,
265265
pub node_name: String,
266266
}
267-
268-
/// The pod this Toleration is attached to tolerates any taint that matches
269-
/// the triple <key,value,effect> using the matching operator <operator>.
270-
#[derive(Default, Clone, Debug)]
271-
pub struct Toleration {
272-
/// Key is the taint key that the toleration applies to. Empty means match all taint keys.
273-
/// If the key is empty, operator must be Exists; this combination means to match all values and all keys.
274-
pub key: Option<TaintKey>,
275-
/// Operator represents a key's relationship to the value.
276-
/// Valid operators are Exists and Equal. Defaults to Equal.
277-
pub operator: TolerationOperator,
278-
/// Effect indicates the taint effect to match. None means match all taint effects.
279-
/// When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
280-
pub effect: Option<TaintEffect>,
281-
pub value: String,
282-
}
283-
284-
impl Toleration {
285-
pub fn tolerate(&self, taint: &Taint) -> bool {
286-
if self.effect.is_some() && self.effect.as_ref().unwrap() != &taint.effect {
287-
return false;
288-
}
289-
if self.key.is_some() && self.key.as_ref().unwrap() != &taint.key {
290-
return false;
291-
}
292-
match self.operator {
293-
TolerationOperator::Equal => self.value == taint.value,
294-
TolerationOperator::Exists => true,
295-
}
296-
}
297-
}
298-
299-
#[derive(Clone, Debug)]
300-
pub enum TolerationOperator {
301-
Exists,
302-
Equal,
303-
}
304-
305-
impl Default for TolerationOperator {
306-
fn default() -> Self {
307-
Self::Equal
308-
}
309-
}
310-
311-
#[derive(Clone, PartialEq, Eq, Debug)]
312-
pub enum TaintEffect {
313-
NoSchedule,
314-
PreferNoSchedule,
315-
NoExecute,
316-
}
317-
318-
#[derive(Clone, Debug)]
319-
pub struct Taint {
320-
pub key: TaintKey,
321-
pub value: String,
322-
pub effect: TaintEffect,
323-
}
324-
325-
impl Taint {
326-
pub fn new(key: TaintKey, effect: TaintEffect) -> Self {
327-
Self {
328-
key,
329-
effect,
330-
value: String::new(),
331-
}
332-
}
333-
}
334-
335-
#[derive(Clone, PartialEq, Eq, Debug)]
336-
pub enum TaintKey {
337-
NodeNotReady,
338-
NodeUnreachable,
339-
NodeUnschedulable,
340-
NodeMemoryPressure,
341-
NodeDiskPressure,
342-
NodeNetworkUnavailable,
343-
NodeOutOfService,
344-
}

0 commit comments

Comments
 (0)