v0.5.0
版本发布时间: 2020-09-23 02:33:04
krustlet/krustlet最新发布版本:v1.0.0-alpha.1(2021-07-28 01:06:02)
Krustlet v0.5.0 is mostly an "under the hood" release if you are just a consumer of Krustlet, although there still are a few useful feature adds! However, if you are using the kubelet
crate, there have been significant API changes that lay the groundwork for solid features in the future. These changes are explained below. For more details on what isn't implemented yet, see the Known Issues section.
Because this is pre-release software, there are no backwards compatibility guarantees for the Rust API or functionality. However, we will do our best to document any breaking changes in future releases.
Caveats
Please note that this is NOT production-ready software, but it is in a usable state. The WASI standard and wasmtime are still under heavy development, and because of this there are key features (like networking) that are missing; these will appear in the future. However, there is networking support available in wasCC.
Notable Features/Changes
- An entirely new and shiny state machine API for the
Provider
trait. This includes a newState
trait to be use in constructing a state machine - Krustlet now supports Kubernetes 1.19. However, this came with a slight breaking change (see next section)
- You can now mount individual items from
Secrets
andConfigMaps
into pods -
ImagePullSecrets
are now supported - For those developing on Krustlet, there are now some additional e2e testing tools and justfile targets
Breaking changes
Due to the requirements in Kubernetes 1.19, Krustlet no longer can self label its node object with a role. Full details about why this change was needed can be found here. In practice, this means your node selectors on Pods meant to be run on a Krustlet node should not rely on the role. It is a little unclear what is the best practice here from the Kubernetes standpoint (automation after node joining or some other sort of reconciliation process), but in our experience we find it best to select on the architecture like so:
nodeSelector:
beta.kubernetes.io/os: linux
beta.kubernetes.io/arch: wasm32-wascc
You can see various examples of selectors in our demos.
New Provider API and State Machine
This section details the major changes to the kubelet
crate API. If you do not consume this crate or write your own provider, feel free to skip to the next section.
First and foremost, the Provider
trait has been hugely slimmed down. The current trait (with new members commented) as of publishing time is:
pub trait Provider: Sized {
/// The state that is passed between Pod state handlers.
type PodState: 'static + Send + Sync + AsyncDrop;
/// The initial state for Pod state machine.
type InitialState: Default + State<Self::PodState>;
/// The a state to handle early Pod termination.
type TerminatedState: Default + State<Self::PodState>;
const ARCH: &'static str;
async fn node(&self, _builder: &mut Builder) -> anyhow::Result<()> {
Ok(())
}
/// Hook to allow provider to introduced shared state into Pod state.
async fn initialize_pod_state(&self, pod: &Pod) -> anyhow::Result<Self::PodState>;
async fn logs(
&self,
namespace: String,
pod: String,
container: String,
sender: Sender,
) -> anyhow::Result<()>;
async fn exec(&self, _pod: Pod, _command: String) -> anyhow::Result<Vec<String>> {
Err(NotImplementedError.into())
}
async fn env_vars(
container: &Container,
pod: &Pod,
client: &kube::Client,
) -> HashMap<String, String> {
...
}
}
We have removed all of the separate functions for handling the basic CRUD operations as those are now handled by the new state machine (covered below). A few important details about the new parts of the Provider
: The InitialState
and TerminatedState
allow Provider authors to specify what the starting state for a Pod is and the state it should jump to if deleted. The PodState
and initialize_pod_state
are used in conjunction to allow your Provider to exposed shared state (often stored within the Provider itself) to all of the pods. A simple example of this is the set of currently assigned ports used in the waSCC provider. This shared state must implement the custom AsyncDrop
as Rust currently has no async drop standard.
In this new paradigm, providers are expected to provide a full state machine for the lifecycle of the pod. This new design allows for each step of processing to be encapsulated in its own state (e.g. pulling images is one state, starting containers is another). At the heart of this is one new trait, State
, and one new enum
: Transition
as shown below:
pub trait State<PodState>: Sync + Send + 'static + std::fmt::Debug {
/// Provider supplies method to be executed when in this state.
async fn next(
self: Box<Self>,
pod_state: &mut PodState,
pod: &Pod,
) -> anyhow::Result<Transition<PodState>>;
/// Provider supplies JSON status patch to apply when entering this state.
async fn json_status(
&self,
pod_state: &mut PodState,
pod: &Pod,
) -> anyhow::Result<serde_json::Value>;
}
pub enum Transition<PodState> {
/// Transition to new state.
Next(StateHolder<PodState>),
/// This is a terminal node of the state graph.
Complete(anyhow::Result<()>),
}
Each state in your machine must implement the State
trait. The json_status
function is called when entering into the state to update the status in Kubernetes. The next
function is called in an iterative fashion to walk through the state machine. Transitions to other states are done using the Transition
next
method, which abstracts away some boxing and other things behind the scenes to construct a Transition::Next
.
For additional safety, each state must explicitly mark what its next possible states are using the TransitionTo
trait, providing compile time guarantees that you aren't transitioning into a state you aren't expecting.
To tie it all together, here is a super simple implementation of a state:
use kubelet::state::{Transition, State, TransitionTo};
use kubelet::pod::Pod;
#[derive(Debug)]
struct TestState;
impl TransitionTo<TestState> for TestState {}
struct PodState;
#[async_trait::async_trait]
impl State<PodState> for TestState {
async fn next(
self: Box<Self>,
_pod_state: &mut PodState,
_pod: &Pod,
) -> anyhow::Result<Transition<PodState>> {
Ok(Transition::next(self, TestState))
}
async fn json_status(
&self,
_pod_state: &mut PodState,
_pod: &Pod,
) -> anyhow::Result<serde_json::Value> {
Ok(serde_json::json!(null))
}
}
If you are interested in the technical details and design decisions behind the state machine, there will be a forthcoming blog post on https://deislabs.io (we will update the link here when it releases). Please note that this API is still needs some polishing work. We don't expect any more major changes like what is in this release, but there will be various ergonomic changes to make it easier to use as we continue to iterate.
For real world examples of a provider implementation, please take a look at the WASI and waSCC providers in Krustlet. See the crate documentation for full documentation and more examples.
Known Issues/Missing Features
- Cloud volume mounting support
- Kubernetes networking support. The waSCC provider currently exposes the service on one of the node's ports, but there is nothing that updates
Service
s orEndpoint
s - Support for all pod phases/conditions (
ContainerCreating
,CrashLoopBackoff
, etc.). However, please note that running and error conditions are supported, so you'll know if your pod is in an erroneous state - Unsupported workloads (such as those dropped automatically onto a node like kube-proxy) can enter an error loop. This is more of a nuisance that will cause some logging noise, but not impact the running of Krustlet
- Modifying a bare pod's image is not implemented. Nothing will error, but Krustlet will not restart the "container"
- TLS bootstrapping does not auto-renew certificates when they are close to expiry
What's next?
Our next anticipated version is 0.6.0 (although we will cut a 0.5.1 if necessary). You can see a full list of issues planned for 0.6 in the milestone. Our main focus for 0.6 will be around supporting cloud provider volumes and continued API ergonomic enhancements. During the next release cycle, we will also be moving out the waSCC provider to its own repo. Full details will be in the 0.6 release notes.
Thanks
We want to express a huge thanks to all of those in the community who contributed to this release. We appreciate your efforts in making this project a success.
We also would like to call out @kflansburg's herculean efforts with the new state machine API and refactor. He recently joined us as a core maintainer and took the lead on this massive chunk of work. If you see him on the interwebs, please say thanks!
Contributors to 0.5
- @kflansburg
- @itowlson
- @bacongobbler
- @thomastaylor312
- @jlegrone
- @Porges
Installation
Download Krustlet 0.5.0:
Check out our installation docs for information on how to install Krustlet.