Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
635cf587
Commit
635cf587
authored
Feb 02, 2016
by
k8s-merge-robot
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #12802 from yujuhong/kubelet_proposal
Auto commit by PR queue bot
parents
072bfd40
b8b532b9
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
230 additions
and
0 deletions
+230
-0
pleg.png
docs/proposals/pleg.png
+0
-0
pod-lifecycle-event-generator.md
docs/proposals/pod-lifecycle-event-generator.md
+230
-0
No files found.
docs/proposals/pleg.png
0 → 100644
View file @
635cf587
47.9 KB
docs/proposals/pod-lifecycle-event-generator.md
0 → 100644
View file @
635cf587
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
<!-- BEGIN STRIP_FOR_RELEASE -->
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<h2>
PLEASE NOTE: This document applies to the HEAD of the source tree
</h2>
If you are using a released version of Kubernetes, you should
refer to the docs that go with that version.
Documentation for other releases can be found at
[
releases.k8s.io
](
http://releases.k8s.io
)
.
</strong>
--
<!-- END STRIP_FOR_RELEASE -->
<!-- END MUNGE: UNVERSIONED_WARNING -->
# Kubelet: Pod Lifecycle Event Generator (PLEG)
In Kubernetes, Kubelet is a per-node daemon that manages the pods on the node,
driving the pod states to match their pod specifications (specs). To achieve
this, Kubelet needs to react to changes in both (1) pod specs and (2) the
container states. For the former, Kubelet watches the pod specs changes from
multiple sources; for the latter, Kubelet polls the container runtime
periodically (e.g., 10s) for the latest states for all containers.
Polling incurs non-negligible overhead as the number of pods/containers increases,
and is exacerbated by Kubelet's parallelism -- one worker (goroutine) per pod, which
queries the container runtime individually. Periodic, concurrent, large number
of requests causes high CPU usage spikes (even when there is no spec/state
change), poor performance, and reliability problems due to overwhelmed container
runtime. Ultimately, it limits Kubelet's scalability.
(Related issues reported by users:
[
#10451
](
https://issues.k8s.io/10451
)
,
[
#12099
](
https://issues.k8s.io/12099
)
,
[
#12082
](
https://issues.k8s.io/12082
)
)
## Goals and Requirements
The goal of this proposal is to improve Kubelet's scalability and performance
by lowering the pod management overhead.
-
Reduce unnecessary work during inactivity (no spec/state changes)
-
Lower the concurrent requests to the container runtime.
The design should be generic so that it can support different container runtimes
(e.g., Docker and rkt).
## Overview
This proposal aims to replace the periodic polling with a pod lifecycle event
watcher.

## Pod Lifecycle Event
A pod lifecycle event interprets the underlying container state change at the
pod-level abstraction, making it container-runtime-agnostic. The abstraction
shields Kubelet from the runtime specifics.
```
go
type
PodLifeCycleEventType
string
const
(
ContainerStarted
PodLifeCycleEventType
=
"ContainerStarted"
ContainerStopped
PodLifeCycleEventType
=
"ContainerStopped"
NetworkSetupCompleted
PodLifeCycleEventType
=
"NetworkSetupCompleted"
NetworkFailed
PodLifeCycleEventType
=
"NetworkFailed"
)
// PodLifecycleEvent is an event reflects the change of the pod state.
type
PodLifecycleEvent
struct
{
// The pod ID.
ID
types
.
UID
// The type of the event.
Type
PodLifeCycleEventType
// The accompanied data which varies based on the event type.
Data
interface
{}
}
```
Using Docker as an example, starting of a POD infra container would be
translated to a NetworkSetupCompleted
`pod lifecycle event.
## Detect Changes in Container States Via Relisting
In order to generate pod lifecycle events, PLEG needs to detect changes in
container states. We can achieve this by periodically relisting all containers
(e.g., docker ps). Although this is similar to Kubelet's polling today, it will
only be performed by a single thread (PLEG). This means that we still
benefit from not having all pod workers hitting the container runtime
concurrently. Moreover, only the relevant pod worker would be woken up
to perform a sync.
The upside of relying on relisting is that it is container runtime-agnostic,
and requires no external dependency.
### Relist period
The shorter the relist period is, the sooner that Kubelet can detect the
change. Shorter relist period also implies higher cpu usage. Moreover, the
relist latency depends on the underlying container runtime, and usually
increases as the number of containers/pods grows. We should set a default
relist period based on measurements. Regardless of what period we set, it will
likely be significantly shorter than the current pod sync period (10s), i.e.,
Kubelet will detect container changes sooner.
## Impact on the Pod Worker Control Flow
Kubelet is responsible for dispatching an event to the appropriate pod
worker based on the pod ID. Only one pod worker would be woken up for
each event.
Today, the pod syncing routine in Kubelet is idempotent as it always
examines the pod state and the spec, and tries to drive to state to
match the spec by performing a series of operations. It should be
noted that this proposal does not intend to change this property --
the sync pod routine would still perform all necessary checks,
regardless of the event type. This trades some efficiency for
reliability and eliminate the need to build a state machine that is
compatible with different runtimes.
## Leverage Upstream Container Events
Instead of relying on relisting, PLEG can leverage other components which
provide container events, and translate these events into pod lifecycle
events. This will further improve Kubelet's responsiveness and reduce the
resource usage caused by frequent relisting.
The upstream container events can come from:
(1). *Event stream provided by each container runtime*
Docker's API exposes an [event
stream](https://docs.docker.com/reference/api/docker_remote_api_v1.17/#monitor-docker-s-events).
Nonetheless, rkt does not support this yet, but they will eventually support it
(see [coreos/rkt#1193](https://github.com/coreos/rkt/issues/1193)).
(2). *cgroups event stream by cAdvisor*
cAdvisor is integrated in Kubelet to provide container stats. It watches cgroups
containers using inotify and exposes an event stream. Even though it does not
support rkt yet, it should be straightforward to add such a support.
Option (1) may provide richer sets of events, but option (2) has the advantage
to be more universal across runtimes, as long as the container runtime uses
cgroups. Regardless of what one chooses to implement now, the container event
stream should be easily swappable with a clearly defined interface.
Note that we cannot solely rely on the upstream container events due to the
possibility of missing events. PLEG should relist infrequently to ensure no
events are missed.
## Generate Expected Events
*This is optional for PLEGs which performs only relisting, but required for
PLEGs that watch upstream events.*
A pod worker's actions could lead to pod lifecycle events (e.g.,
create/kill a container), which the worker would not observe until
later. The pod worker should ignore such events to avoid unnecessary
work.
For example, assume a pod has two containers, A and B. The worker
- Creates container A
- Receives an event `
(ContainerStopped, B)
`
- Receives an event `
(ContainerStarted, A)
`
The worker should ignore the `
(ContainerStarted, A)
` event since it is
expected. Arguably, the worker could process `
(ContainerStopped, B)
`
as soon as it receives the event, before observing the creation of
A. However, it is desirable to wait until the expected event
`
(ContainerStarted, A)
` is observed to keep a consistent per-pod view
at the worker. Therefore, the control flow of a single pod worker
should adhere to the following rules:
1. Pod worker should process the events sequentially.
2. Pod worker should not start syncing until it observes the outcome of its own
actions in the last sync to maintain a consistent view.
In other words, a pod worker should record the expected events, and
only wake up to perform the next sync until all expectations are met.
- Creates container A, records an expected event `
(ContainerStarted, A)
`
- Receives `
(ContainerStopped, B)
`; stores the event and goes back to sleep.
- Receives `
(ContainerStarted, A)
`; clears the expectation. Proceeds to handle
`
(ContainerStopped, B)
`.
We should set an expiration time for each expected events to prevent the worker
from being stalled indefinitely by missing events.
## TODOs for v1.2
For v1.2, we will add a generic PLEG which relists periodically, and leave
adopting container events for future work. We will also *not* implement the
optimization that generate and filters out expected events to minimize
redundant syncs.
- Add a generic PLEG using relisting. Modify the container runtime interface
to provide all necessary information to detect container state changes
in `
GetPods()
`
(#13571).
-
Benchmark docker to adjust relising frequency.
-
Fix/adapt features that rely on frequent, periodic pod syncing.
*
Liveness/Readiness probing: Create a separate probing manager using
explicitly container probing period
[
#10878
](
https://issues.k8s.io/10878
)
.
*
Instruct pod workers to set up a wake-up call if syncing failed, so that
it can retry.
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[

]()
<!-- END MUNGE: GENERATED_ANALYTICS -->
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment