Repository: kubermatic/machine-controller
Pull request #802 (2020-07-31 10:01:01)

Support Flatcar in Packet cloud provider
To allow Flatcar to be used as one of the operating systems, we need to update `getNameForOS()` so it also accepts the input value `flatcar` in `operatingSystem` of the provider config.

### Optional Release Note:

```release-note
support Flatcar in Packet cloud provider
```

kubermatic-bot: @dongsupark: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our [release note process](https://git.k8s.io/community/contributors/guide/release-notes.md) to remove it.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
kubermatic-bot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubermatic/machine-controller/pull/802#" title="Author self-approved">dongsupark</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **irozzo-1a**
You can assign the PR to them by writing `/assign @irozzo-1a` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubermatic%2Fmachine-controller).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubermatic/machine-controller/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["irozzo-1a"]} -->
kubermatic-bot: Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.

:memo: **Please follow instructions in the [contributing guide](https://github.com/kubermatic/machine-controller/blob/master/CONTRIBUTING.md) to update your commits with the DCO**

Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).

**The list of commits missing DCO signoff**:

- [895254f](https://github.com/kubermatic/machine-controller/commits/895254fdb69c6f9caa7f1a65f00de67fcfc282af) Support Flatcar in Packet cloud provider

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>

kubermatic-bot: Hi @dongsupark. Thanks for your PR.

I'm waiting for a [kubermatic](https://github.com/orgs/kubermatic/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://github.com/orgs/kubermatic/people) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=kubermatic%2Fmachine-controller).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

dongsupark: Done. Updated the Packet e2e test.
Thanks for the review.
kubermatic-bot: LGTM label has been added.  <details>Git tree hash: ac44bbda5b544ab4df37de3b9c299bb550524147</details>
kubermatic-bot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubermatic/machine-controller/pull/802#" title="Author self-approved">dongsupark</a>*, *<a href="https://github.com/kubermatic/machine-controller/pull/802#pullrequestreview-459111764" title="Approved">xmudrii</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubermatic%2Fmachine-controller).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/kubermatic/machine-controller/blob/master/OWNERS)~~ [xmudrii]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
xmudrii: /test pull-machine-controller-e2e-aws-ebs-encryption-enabled
kubermatic-bot: @dongsupark: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-machine-controller-e2e-packet | 0e841000f80b07c96de33c1b0191a98c862646b0 | [link](https://public-prow.loodse.com/view/gs/prow-dev-public-data/pr-logs/pull/kubermatic_machine-controller/802/pull-machine-controller-e2e-packet/1289164879978041345) | `/test pull-machine-controller-e2e-packet`

[Full PR test history](https://public-prow.loodse.com/pr-history?org=kubermatic&repo=machine-controller&pr=802)

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
kubermatic-bot: @dongsupark: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-machine-controller-e2e-packet | 0e841000f80b07c96de33c1b0191a98c862646b0 | [link](https://public-prow.loodse.com/view/gs/prow-dev-public-data/pr-logs/pull/kubermatic_machine-controller/802/pull-machine-controller-e2e-packet/1289164879978041345) | `/test pull-machine-controller-e2e-packet`
pull-machine-controller-e2e-azure | 0e841000f80b07c96de33c1b0191a98c862646b0 | [link](https://public-prow.loodse.com/view/gs/prow-dev-public-data/pr-logs/pull/kubermatic_machine-controller/802/pull-machine-controller-e2e-azure/1289164879961264128) | `/test pull-machine-controller-e2e-azure`

[Full PR test history](https://public-prow.loodse.com/pr-history?org=kubermatic&repo=machine-controller&pr=802)

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
dongsupark: /retest
kubermatic-bot: @dongsupark: Cannot trigger testing until a trusted user reviews the PR and leaves an `/ok-to-test` message.

<details>

In response to [this](https://github.com/kubermatic/machine-controller/pull/802#issuecomment-667106861):

>/retest


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
kubermatic-triage-bot: /retest
This bot automatically retries jobs that failed/flaked on approved PRs

Review the [full test history](https://prow.loodse.com/pr-history/?org=kubermatic&repo=machine-controller&pr=802)

Silence the bot with an `/lgtm cancel` or `/hold` comment for consistent failures.

Also, here is a cat.
/meow
kubermatic-bot: @kubermatic-triage-bot: ![cat image](https://cdn2.thecatapi.com/images/bfg.jpg)

<details>

In response to [this](https://github.com/kubermatic/machine-controller/pull/802#issuecomment-667142484):

>/retest
>This bot automatically retries jobs that failed/flaked on approved PRs
>
>Review the [full test history](https://prow.loodse.com/pr-history/?org=kubermatic&repo=machine-controller&pr=802)
>
>Silence the bot with an `/lgtm cancel` or `/hold` comment for consistent failures.
>
>Also, here is a cat.
>/meow


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
xmudrii: /hold
we are aware of the problem and we are working on fixing it
kubermatic-bot: @dongsupark: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-machine-controller-e2e-packet | 0e841000f80b07c96de33c1b0191a98c862646b0 | [link](https://public-prow.loodse.com/view/gs/prow-dev-public-data/pr-logs/pull/kubermatic_machine-controller/802/pull-machine-controller-e2e-packet/1289203497278902272) | `/test pull-machine-controller-e2e-packet`

[Full PR test history](https://public-prow.loodse.com/pr-history?org=kubermatic&repo=machine-controller&pr=802)

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/.gitignore b/.gitignore
index 3a38c56d..25786938 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
 .idea
-machine-controller*
+/machine-controller*
 .terraform
 terraform.tfstate
 terraform.tfstate.backup
@@ -12,3 +12,4 @@ examples/*.pem
 examples/*.csr
 examples/*.srl
 /webhook
+/vendor
diff --git a/Makefile b/Makefile
index b6106bcb..0f40086a 100644
--- a/Makefile
+++ b/Makefile
@@ -31,7 +31,7 @@ LDFLAGS ?= -ldflags '-s -w'
 
 IMAGE_TAG = \
 		$(shell echo $$(git rev-parse HEAD && if [[ -n $$(git status --porcelain) ]]; then echo '-dirty'; fi)|tr -d ' ')
-IMAGE_NAME = $(REGISTRY)/$(REGISTRY_NAMESPACE)/machine-controller:$(IMAGE_TAG)
+IMAGE_NAME ?= $(REGISTRY)/$(REGISTRY_NAMESPACE)/machine-controller:$(IMAGE_TAG)
 
 OS = centos coreos ubuntu sles rhel flatcar
 USERDATA_BIN = $(patsubst %, machine-controller-userdata-%, $(OS))
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index 52defe09..dae8cdf1 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -3,7 +3,6 @@
 aliases:
   machine-controller-maintainers:
     - irozzo-1A
-    - kdomanski
     - kron4eg
     - moadqassem
     - moelsayed
diff --git a/cmd/machine-controller/main.go b/cmd/machine-controller/main.go
index 9c3dcfbe..1614441d 100644
--- a/cmd/machine-controller/main.go
+++ b/cmd/machine-controller/main.go
@@ -82,6 +82,7 @@ var (
 	nodeRegistryMirrors    string
 	nodePauseImage         string
 	nodeHyperkubeImage     string
+	nodeKubeletRepository  string
 )
 
 const (
@@ -165,7 +166,8 @@ func main() {
 	flag.StringVar(&nodeInsecureRegistries, "node-insecure-registries", "", "Comma separated list of registries which should be configured as insecure on the container runtime")
 	flag.StringVar(&nodeRegistryMirrors, "node-registry-mirrors", "", "Comma separated list of Docker image mirrors")
 	flag.StringVar(&nodePauseImage, "node-pause-image", "", "Image for the pause container including tag. If not set, the kubelet default will be used: https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/")
-	flag.StringVar(&nodeHyperkubeImage, "node-hyperkube-image", "k8s.gcr.io/hyperkube-amd64", "Image for the hyperkube container excluding tag.")
+	flag.StringVar(&nodeHyperkubeImage, "node-hyperkube-image", "k8s.gcr.io/hyperkube-amd64", "Image for the hyperkube container excluding tag. Only has effect on CoreOS Container Linux and Flatcar Linux, and for kubernetes < 1.18.")
+	flag.StringVar(&nodeKubeletRepository, "node-kubelet-repository", "quay.io/poseidon/kubelet", "Repository for the kubelet container. Only has effect on Flatcar Linux, and for kubernetes >= 1.18.")
 	flag.BoolVar(&nodeCSRApprover, "node-csr-approver", false, "Enable NodeCSRApprover controller to automatically approve node serving certificate requests.")
 
 	flag.Parse()
@@ -198,13 +200,23 @@ func main() {
 	if err := clusterv1alpha1.AddToScheme(scheme.Scheme); err != nil {
 		klog.Fatalf("failed to add clusterv1alpha1 api to scheme: %v", err)
 	}
+
 	// Check if the hyperkube image has a tag set
 	hyperkubeImageRef, err := reference.Parse(nodeHyperkubeImage)
 	if err != nil {
-		klog.Fatalf("failed to parse --node-hyperkube-image %s: %v", nodeHyperkubeImage, err)
+		klog.Fatalf("failed to parse -node-hyperkube-image %s: %v", nodeHyperkubeImage, err)
 	}
 	if _, ok := hyperkubeImageRef.(reference.NamedTagged); ok {
-		klog.Fatalf("--node-hyperkube-image must not contain a tag. The tag will be dynamically set for each Machine.")
+		klog.Fatalf("-node-hyperkube-image must not contain a tag. The tag will be dynamically set for each Machine.")
+	}
+
+	// Check if the kubelet image has a tag set
+	kubeletRepoRef, err := reference.Parse(nodeKubeletRepository)
+	if err != nil {
+		klog.Fatalf("failed to parse -node-hyperkube-image %s: %v", nodeHyperkubeImage, err)
+	}
+	if _, ok := kubeletRepoRef.(reference.NamedTagged); ok {
+		klog.Fatalf("-node-kubelet-image must not contain a tag. The tag will be dynamically set for each Machine.")
 	}
 
 	cfg, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfig)
@@ -246,11 +258,12 @@ func main() {
 		skipEvictionAfter:     skipEvictionAfter,
 		nodeCSRApprover:       nodeCSRApprover,
 		node: machinecontroller.NodeSettings{
-			ClusterDNSIPs:  clusterDNSIPs,
-			HTTPProxy:      nodeHTTPProxy,
-			NoProxy:        nodeNoProxy,
-			HyperkubeImage: nodeHyperkubeImage,
-			PauseImage:     nodePauseImage,
+			ClusterDNSIPs:     clusterDNSIPs,
+			HTTPProxy:         nodeHTTPProxy,
+			NoProxy:           nodeNoProxy,
+			HyperkubeImage:    nodeHyperkubeImage,
+			KubeletRepository: nodeKubeletRepository,
+			PauseImage:        nodePauseImage,
 		},
 	}
 	if parsedJoinClusterTimeout != nil {
diff --git a/docs/network-restrictions.md b/docs/network-restrictions.md
index 5e4da469..15b76c52 100644
--- a/docs/network-restrictions.md
+++ b/docs/network-restrictions.md
@@ -27,16 +27,35 @@ If that image won't be accessible from the node, a custom image can be specified
 -node-pause-image="192.168.1.1:5000/kubernetes/pause:3.1"
 ```
 
-For ContainerLinux nodes the [hyperkube](https://github.com/kubernetes/kubernetes/tree/master/cluster/images/hyperkube) image must be accessible as well.
-This is due to the usage of the [kubelet-wrapper](https://github.com/coreos/coreos-kubernetes/blob/master/Documentation/kubelet-wrapper.md).
 
-By default the image `k8s.gcr.io/hyperkube-amd64` will be used.
-If that image won't be accessible from the node, a custom image can be specified on the machine-controller:
+## Kubelet images
+
+### CoreOS ContainerLinux
+For ContainerLinux nodes, the [hyperkube][1] image must be accessible as well. This is due to the usage of the
+[kubelet-wrapper][2].
+
+By default the image `k8s.gcr.io/hyperkube-amd64` will be used. If that image won't be accessible from the node, a
+custom image can be specified on the machine-controller:
+```bash
+# Do not set a tag. The tag depends on the used Kubernetes version of a machine.
+# Example:
+# A Node using v1.14.2 would use 192.168.1.1:5000/kubernetes/hyperkube-amd64:v1.14.2
+-node-hyperkube-image="192.168.1.1:5000/kubernetes/hyperkube-amd64"
+```
+
+### Flatcar Linux
+For Flatcar Linux nodes, the [hyperkube][1] or [kubelet][3] image must be accessible as well. This is due to the fact
+that kubelet is running as a docker container. For kubelet version `< 1.18` hyperkube will be used, otherwise `kubelet`
+image.
+
+By default the image `quay.io/poseidon/kubelet` will be used. If that image won't be accessible from the node, a custom
+image can be specified on the machine-controller:
 ```bash
 # Do not set a tag. The tag depends on the used Kubernetes version of a machine.
 # Example:
 # A Node using v1.14.2 would use 192.168.1.1:5000/kubernetes/hyperkube-amd64:v1.14.2
 -node-hyperkube-image="192.168.1.1:5000/kubernetes/hyperkube-amd64"
+-node-kubelet-image="192.168.1.1:5000/my-custom/kubelet-amd64"
 ```
 
 # Insecure registries
@@ -45,3 +64,7 @@ If nodes require access to insecure registries, all registries must be specified
 ```bash
 --node-insecure-registries="192.168.1.1:5000,10.0.0.1:5000"
 ```
+
+[1]: https://console.cloud.google.com/gcr/images/google-containers/GLOBAL/hyperkube
+[2]: https://github.com/coreos/coreos-kubernetes/blob/master/Documentation/kubelet-wrapper.md
+[3]: https://quay.io/poseidon/kubelet
diff --git a/docs/operating-system.md b/docs/operating-system.md
index 08c034cb..7cbb2faf 100644
--- a/docs/operating-system.md
+++ b/docs/operating-system.md
@@ -4,15 +4,15 @@
 
 ### Cloud provider
 
-|   | Ubuntu | Container Linux | CentOS | RHEL | SLES |
-|---|---|---|---|---|---|
-| AWS | ✓ | ✓ | ✓ | ✓ | ✓ |
-| Azure | ✓ | ✓ | ✓ | ✓ | x |
-| Digitalocean  | ✓ | ✓ | ✓ | x | x |
-| Google Cloud Platform | ✓ | ✓ | x | ✓ | x |
-| Hetzner | ✓ | x | ✓ | x | x |
-| Packet | ✓ | ✓ | ✓ | x | x |
-| Openstack | ✓ | ✓ | ✓ | ✓ | x |
+|   | Ubuntu | Container Linux | CentOS | Flatcar | RHEL | SLES |
+|---|---|---|---|---|---|---|
+| AWS | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Azure | ✓ | ✓ | ✓ | ✓ | ✓ | x |
+| Digitalocean  | ✓ | ✓ | ✓ | x | x | x |
+| Google Cloud Platform | ✓ | ✓ | x | x | ✓ | x |
+| Hetzner | ✓ | x | ✓ | x | x | x |
+| Packet | ✓ | ✓ | ✓ | x | x | x |
+| Openstack | ✓ | ✓ | ✓ | x | ✓ | x |
 
 ## Configuring a operating system
 
diff --git a/go.mod b/go.mod
index 14bfed3a..4c6b9f4e 100644
--- a/go.mod
+++ b/go.mod
@@ -62,7 +62,6 @@ require (
 	go.uber.org/zap v1.13.0 // indirect
 	go4.org v0.0.0-20200104003542-c7e774b10ea0 // indirect
 	golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6
-	golang.org/x/exp v0.0.0-20200213203834-85f925bdd4d0 // indirect
 	golang.org/x/lint v0.0.0-20200130185559-910be7a94367 // indirect
 	golang.org/x/mod v0.2.0 // indirect
 	golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect
@@ -70,7 +69,6 @@ require (
 	golang.org/x/sys v0.0.0-20200217220822-9197077df867 // indirect
 	golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
 	golang.org/x/tools v0.0.0-20200219054238-753a1d49df85 // indirect
-	gonum.org/v1/gonum v0.6.2 // indirect
 	google.golang.org/api v0.6.0
 	google.golang.org/appengine v1.6.5 // indirect
 	google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce // indirect
@@ -85,8 +83,6 @@ require (
 	k8s.io/apiextensions-apiserver v0.16.4
 	k8s.io/apimachinery v0.16.4
 	k8s.io/client-go v12.0.0+incompatible
-	k8s.io/code-generator v0.16.4
-	k8s.io/gengo v0.0.0-20200205140755-e0e292d8aa12 // indirect
 	k8s.io/klog v1.0.0
 	k8s.io/kube-openapi v0.0.0-20200204173128-addea2498afe // indirect
 	k8s.io/kubelet v0.16.4
diff --git a/go.sum b/go.sum
index 81be0052..47cdd75a 100644
--- a/go.sum
+++ b/go.sum
@@ -2,7 +2,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo=
 cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
-dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 github.com/Azure/azure-sdk-for-go v31.1.0+incompatible h1:5SzgnfAvUBdBwNTN23WLfZoCt/rGhLvd7QdCAaFXgY4=
 github.com/Azure/azure-sdk-for-go v31.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
@@ -53,7 +52,6 @@ github.com/ajeddeloh/go-json v0.0.0-20170920214419-6a2fe990e083 h1:uwcvnXW76Y0rH
 github.com/ajeddeloh/go-json v0.0.0-20170920214419-6a2fe990e083/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c=
 github.com/ajeddeloh/yaml v0.0.0-20170912190910-6b94386aeefd h1:NlKlOv3aVJ5ODMC0JWPvddw05KENkL3cZttIuu8kJRo=
 github.com/ajeddeloh/yaml v0.0.0-20170912190910-6b94386aeefd/go.mod h1:idhzw68Q7v4j+rQ2AGyq3OlZW2Jij9mdmGA4/Sk6J0E=
-github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
@@ -135,7 +133,6 @@ github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
 github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
 github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -144,7 +141,6 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
 github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is=
 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
@@ -213,7 +209,6 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
 github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
-github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -311,7 +306,6 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
 github.com/k8snetworkplumbingwg/network-attachment-definition-client v0.0.0-20191119172530-79f836b90111/go.mod h1:MP2HbArq3QT+oVp8pmtHNZnSnkhdkHtDnc7h6nJXmBU=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@@ -497,18 +491,11 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vK
 golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 h1:Sy5bstxEqwwbYs6n0/pBuxKENqOeZUgD45Gp3Q3pqLg=
 golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495 h1:I6A9Ag9FpEKOjcKrRNjQkPHawoXIhKyTGfvvjFAiiAk=
 golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
-golang.org/x/exp v0.0.0-20200213203834-85f925bdd4d0 h1:tm4MMkqdvahr61SDpB2su1XZfifRH4XMRQODT1z3p2Q=
-golang.org/x/exp v0.0.0-20200213203834-85f925bdd4d0/go.mod h1:IX6Eufr4L0ErOUlzqX/aFlHqsiKZRbV42Kb69e9VsTE=
-golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -519,11 +506,9 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
 golang.org/x/lint v0.0.0-20200130185559-910be7a94367 h1:0IiAsCRByjO2QjX7ZPkw5oU9x+n1YqRL802rjC0c3Aw=
 golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
 golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
-golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
 golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -582,7 +567,6 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190927073244-c990c680b611/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200217220822-9197077df867 h1:JoRuNIf+rpHl+VhScRQQvzbHed86tKkqwPMV34T8myw=
 golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -597,7 +581,6 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZe
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -617,7 +600,6 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn
 golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200219054238-753a1d49df85 h1:XNHaQ2CZDl/SjEZlUXGh7+OQvfLuFgmk3oNWkCFfERE=
 golang.org/x/tools v0.0.0-20200219054238-753a1d49df85/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -627,15 +609,11 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0=
 gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
-gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
 gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw=
 gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
-gonum.org/v1/gonum v0.6.2 h1:4r+yNT0+8SWcOkXP+63H2zQbN+USnC73cjGUxnDF94Q=
-gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
 gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
 gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts=
 gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
-gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/api v0.6.0 h1:2tJEkRfnZL5g1GeBUlITh/rqT5HG3sFcoVCUUxmgJ2g=
 google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
@@ -731,8 +709,6 @@ k8s.io/gengo v0.0.0-20181106084056-51747d6e00da/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/gengo v0.0.0-20190907103519-ebc107f98eab/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
-k8s.io/gengo v0.0.0-20200205140755-e0e292d8aa12 h1:pZzawYyz6VRNPVYpqGv61LWCimQv1BihyeqFrp50/G4=
-k8s.io/gengo v0.0.0-20200205140755-e0e292d8aa12/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
 k8s.io/klog v0.0.0-20190306015804-8e90cee79f82/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
 k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
@@ -762,7 +738,6 @@ modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
 modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
 modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
 modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
-rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
 sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9NPsg=
 sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
 sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
diff --git a/hack/boilerplate/boilerplate.py b/hack/boilerplate/boilerplate.py
index 1ae18a07..b6e21897 100755
--- a/hack/boilerplate/boilerplate.py
+++ b/hack/boilerplate/boilerplate.py
@@ -150,7 +150,7 @@ def file_extension(filename):
     return os.path.splitext(filename)[1].split(".")[-1].lower()
 
 
-skipped_dirs = ['pkg/client', 'vendor', 'hack/verify-boilerplate.sh', 'hack/verify-codegen.sh', 'hack/update-codegen.sh', 'hack/boilerplate/test', 'pkg/userdata/scripts/health-monitor.sh', 'pkg/signals/signal.go', 'pkg/machines/v1alpha1/doc.go', 'pkg/machines/v1alpha1/defaults.go', 'pkg/machines/v1alpha1/zz_generated.deepcopy.go', 'pkg/apis/cluster/v1alpha1/zz_generated.deepcopy.go']
+skipped_dirs = ['pkg/client', 'vendor', 'hack/verify-boilerplate.sh', 'hack/boilerplate/test', 'pkg/userdata/scripts/health-monitor.sh', 'pkg/signals/signal.go', 'pkg/machines/v1alpha1/doc.go', 'pkg/machines/v1alpha1/defaults.go', 'pkg/machines/v1alpha1/zz_generated.deepcopy.go', 'pkg/apis/cluster/v1alpha1/zz_generated.deepcopy.go']
 
 # list all the files contain 'DO NOT EDIT', but are not generated
 skipped_ungenerated_files = ['hack/boilerplate/boilerplate.py']
diff --git a/hack/tools.go b/hack/tools.go
deleted file mode 100644
index 11f32727..00000000
--- a/hack/tools.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// +build tools
-
-/*
-Copyright 2019 The Machine Controller Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Based on: https://github.com/kubernetes/sample-controller/blob/a2c492d/hack/tools.go
-// This package imports things required by build scripts, to force `go mod` to see them as dependencies
-package tools
-
-import _ "k8s.io/code-generator"
diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh
deleted file mode 100755
index 4679f0c0..00000000
--- a/hack/update-codegen.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2017 The Kubernetes Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -o errexit
-set -o nounset
-set -o pipefail
-
-export GOPATH=$(go env GOPATH)
-
-echo Removing old client
-rm -rf "pkg/crd/client"
-SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")
-echo $SCRIPT_ROOT
-/usr/bin/env bash ./vendor/k8s.io/code-generator/generate-groups.sh all \
-    github.com/kubermatic/machine-controller/pkg/client github.com/kubermatic/machine-controller/pkg \
-    machines:v1alpha1 \
-    --go-header-file=${SCRIPT_ROOT}/header.txt
diff --git a/hack/verify-codegen.sh b/hack/verify-codegen.sh
deleted file mode 100755
index fff1fb12..00000000
--- a/hack/verify-codegen.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2017 The Kubernetes Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -o errexit
-set -o nounset
-set -o pipefail
-
-SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/..
-DIFFROOT="${SCRIPT_ROOT}/pkg"
-TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg"
-_tmp="${SCRIPT_ROOT}/_tmp"
-
-cleanup() {
-    rm -rf "${_tmp}"
-}
-trap "cleanup" EXIT SIGINT
-
-cleanup
-
-mkdir -p "${TMP_DIFFROOT}"
-cp -a "${DIFFROOT}"/* "${TMP_DIFFROOT}"
-
-"${SCRIPT_ROOT}/hack/update-codegen.sh"
-echo "diffing ${DIFFROOT} against freshly generated codegen"
-ret=0
-diff -Naupr "${DIFFROOT}" "${TMP_DIFFROOT}" || ret=$?
-cp -a "${TMP_DIFFROOT}"/* "${DIFFROOT}"
-if [[ $ret -eq 0 ]]
-then
-    echo "${DIFFROOT} up to date."
-else
-    echo "${DIFFROOT} is out of date. Please run hack/update-codegen.sh"
-    exit 1
-fi
diff --git a/pkg/apis/plugin/plugin.go b/pkg/apis/plugin/plugin.go
index 07929d71..62365daf 100644
--- a/pkg/apis/plugin/plugin.go
+++ b/pkg/apis/plugin/plugin.go
@@ -52,6 +52,7 @@ type UserDataRequest struct {
 	RegistryMirrors       []string
 	PauseImage            string
 	HyperkubeImage        string
+	KubeletRepository     string
 }
 
 // UserDataResponse contains the responded user data.
diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go
deleted file mode 100644
index 19add175..00000000
--- a/pkg/client/clientset/versioned/clientset.go
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package versioned
-
-import (
-	machinev1alpha1 "github.com/kubermatic/machine-controller/pkg/client/clientset/versioned/typed/machines/v1alpha1"
-	discovery "k8s.io/client-go/discovery"
-	rest "k8s.io/client-go/rest"
-	flowcontrol "k8s.io/client-go/util/flowcontrol"
-)
-
-type Interface interface {
-	Discovery() discovery.DiscoveryInterface
-	MachineV1alpha1() machinev1alpha1.MachineV1alpha1Interface
-}
-
-// Clientset contains the clients for groups. Each group has exactly one
-// version included in a Clientset.
-type Clientset struct {
-	*discovery.DiscoveryClient
-	machineV1alpha1 *machinev1alpha1.MachineV1alpha1Client
-}
-
-// MachineV1alpha1 retrieves the MachineV1alpha1Client
-func (c *Clientset) MachineV1alpha1() machinev1alpha1.MachineV1alpha1Interface {
-	return c.machineV1alpha1
-}
-
-// Discovery retrieves the DiscoveryClient
-func (c *Clientset) Discovery() discovery.DiscoveryInterface {
-	if c == nil {
-		return nil
-	}
-	return c.DiscoveryClient
-}
-
-// NewForConfig creates a new Clientset for the given config.
-func NewForConfig(c *rest.Config) (*Clientset, error) {
-	configShallowCopy := *c
-	if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
-		configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
-	}
-	var cs Clientset
-	var err error
-	cs.machineV1alpha1, err = machinev1alpha1.NewForConfig(&configShallowCopy)
-	if err != nil {
-		return nil, err
-	}
-
-	cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
-	if err != nil {
-		return nil, err
-	}
-	return &cs, nil
-}
-
-// NewForConfigOrDie creates a new Clientset for the given config and
-// panics if there is an error in the config.
-func NewForConfigOrDie(c *rest.Config) *Clientset {
-	var cs Clientset
-	cs.machineV1alpha1 = machinev1alpha1.NewForConfigOrDie(c)
-
-	cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
-	return &cs
-}
-
-// New creates a new Clientset for the given RESTClient.
-func New(c rest.Interface) *Clientset {
-	var cs Clientset
-	cs.machineV1alpha1 = machinev1alpha1.New(c)
-
-	cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
-	return &cs
-}
diff --git a/pkg/client/clientset/versioned/doc.go b/pkg/client/clientset/versioned/doc.go
deleted file mode 100644
index 63aed810..00000000
--- a/pkg/client/clientset/versioned/doc.go
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-// This package has the automatically generated clientset.
-package versioned
diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go
deleted file mode 100644
index 8406ae3a..00000000
--- a/pkg/client/clientset/versioned/fake/clientset_generated.go
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package fake
-
-import (
-	clientset "github.com/kubermatic/machine-controller/pkg/client/clientset/versioned"
-	machinev1alpha1 "github.com/kubermatic/machine-controller/pkg/client/clientset/versioned/typed/machines/v1alpha1"
-	fakemachinev1alpha1 "github.com/kubermatic/machine-controller/pkg/client/clientset/versioned/typed/machines/v1alpha1/fake"
-	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/watch"
-	"k8s.io/client-go/discovery"
-	fakediscovery "k8s.io/client-go/discovery/fake"
-	"k8s.io/client-go/testing"
-)
-
-// NewSimpleClientset returns a clientset that will respond with the provided objects.
-// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
-// without applying any validations and/or defaults. It shouldn't be considered a replacement
-// for a real clientset and is mostly useful in simple unit tests.
-func NewSimpleClientset(objects ...runtime.Object) *Clientset {
-	o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
-	for _, obj := range objects {
-		if err := o.Add(obj); err != nil {
-			panic(err)
-		}
-	}
-
-	cs := &Clientset{tracker: o}
-	cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
-	cs.AddReactor("*", "*", testing.ObjectReaction(o))
-	cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
-		gvr := action.GetResource()
-		ns := action.GetNamespace()
-		watch, err := o.Watch(gvr, ns)
-		if err != nil {
-			return false, nil, err
-		}
-		return true, watch, nil
-	})
-
-	return cs
-}
-
-// Clientset implements clientset.Interface. Meant to be embedded into a
-// struct to get a default implementation. This makes faking out just the method
-// you want to test easier.
-type Clientset struct {
-	testing.Fake
-	discovery *fakediscovery.FakeDiscovery
-	tracker   testing.ObjectTracker
-}
-
-func (c *Clientset) Discovery() discovery.DiscoveryInterface {
-	return c.discovery
-}
-
-func (c *Clientset) Tracker() testing.ObjectTracker {
-	return c.tracker
-}
-
-var _ clientset.Interface = &Clientset{}
-
-// MachineV1alpha1 retrieves the MachineV1alpha1Client
-func (c *Clientset) MachineV1alpha1() machinev1alpha1.MachineV1alpha1Interface {
-	return &fakemachinev1alpha1.FakeMachineV1alpha1{Fake: &c.Fake}
-}
diff --git a/pkg/client/clientset/versioned/fake/doc.go b/pkg/client/clientset/versioned/fake/doc.go
deleted file mode 100644
index 4063d895..00000000
--- a/pkg/client/clientset/versioned/fake/doc.go
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-// This package has the automatically generated fake clientset.
-package fake
diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go
deleted file mode 100644
index 4e9d3f6f..00000000
--- a/pkg/client/clientset/versioned/fake/register.go
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package fake
-
-import (
-	machinev1alpha1 "github.com/kubermatic/machine-controller/pkg/machines/v1alpha1"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	runtime "k8s.io/apimachinery/pkg/runtime"
-	schema "k8s.io/apimachinery/pkg/runtime/schema"
-	serializer "k8s.io/apimachinery/pkg/runtime/serializer"
-	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
-)
-
-var scheme = runtime.NewScheme()
-var codecs = serializer.NewCodecFactory(scheme)
-var parameterCodec = runtime.NewParameterCodec(scheme)
-var localSchemeBuilder = runtime.SchemeBuilder{
-	machinev1alpha1.AddToScheme,
-}
-
-// AddToScheme adds all types of this clientset into the given scheme. This allows composition
-// of clientsets, like in:
-//
-//   import (
-//     "k8s.io/client-go/kubernetes"
-//     clientsetscheme "k8s.io/client-go/kubernetes/scheme"
-//     aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
-//   )
-//
-//   kclientset, _ := kubernetes.NewForConfig(c)
-//   _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
-//
-// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
-// correctly.
-var AddToScheme = localSchemeBuilder.AddToScheme
-
-func init() {
-	v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
-	utilruntime.Must(AddToScheme(scheme))
-}
diff --git a/pkg/client/clientset/versioned/scheme/doc.go b/pkg/client/clientset/versioned/scheme/doc.go
deleted file mode 100644
index 69283270..00000000
--- a/pkg/client/clientset/versioned/scheme/doc.go
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-// This package contains the scheme of the automatically generated clientset.
-package scheme
diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go
deleted file mode 100644
index 80350187..00000000
--- a/pkg/client/clientset/versioned/scheme/register.go
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package scheme
-
-import (
-	machinev1alpha1 "github.com/kubermatic/machine-controller/pkg/machines/v1alpha1"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	runtime "k8s.io/apimachinery/pkg/runtime"
-	schema "k8s.io/apimachinery/pkg/runtime/schema"
-	serializer "k8s.io/apimachinery/pkg/runtime/serializer"
-	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
-)
-
-var Scheme = runtime.NewScheme()
-var Codecs = serializer.NewCodecFactory(Scheme)
-var ParameterCodec = runtime.NewParameterCodec(Scheme)
-var localSchemeBuilder = runtime.SchemeBuilder{
-	machinev1alpha1.AddToScheme,
-}
-
-// AddToScheme adds all types of this clientset into the given scheme. This allows composition
-// of clientsets, like in:
-//
-//   import (
-//     "k8s.io/client-go/kubernetes"
-//     clientsetscheme "k8s.io/client-go/kubernetes/scheme"
-//     aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
-//   )
-//
-//   kclientset, _ := kubernetes.NewForConfig(c)
-//   _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
-//
-// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
-// correctly.
-var AddToScheme = localSchemeBuilder.AddToScheme
-
-func init() {
-	v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
-	utilruntime.Must(AddToScheme(Scheme))
-}
diff --git a/pkg/client/clientset/versioned/typed/machines/v1alpha1/doc.go b/pkg/client/clientset/versioned/typed/machines/v1alpha1/doc.go
deleted file mode 100644
index cb0948c0..00000000
--- a/pkg/client/clientset/versioned/typed/machines/v1alpha1/doc.go
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-// This package has the automatically generated typed clients.
-package v1alpha1
diff --git a/pkg/client/clientset/versioned/typed/machines/v1alpha1/fake/doc.go b/pkg/client/clientset/versioned/typed/machines/v1alpha1/fake/doc.go
deleted file mode 100644
index feb6e2b2..00000000
--- a/pkg/client/clientset/versioned/typed/machines/v1alpha1/fake/doc.go
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-// Package fake has the automatically generated clients.
-package fake
diff --git a/pkg/client/clientset/versioned/typed/machines/v1alpha1/fake/fake_machine.go b/pkg/client/clientset/versioned/typed/machines/v1alpha1/fake/fake_machine.go
deleted file mode 100644
index 5b8eca36..00000000
--- a/pkg/client/clientset/versioned/typed/machines/v1alpha1/fake/fake_machine.go
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package fake
-
-import (
-	v1alpha1 "github.com/kubermatic/machine-controller/pkg/machines/v1alpha1"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	labels "k8s.io/apimachinery/pkg/labels"
-	schema "k8s.io/apimachinery/pkg/runtime/schema"
-	types "k8s.io/apimachinery/pkg/types"
-	watch "k8s.io/apimachinery/pkg/watch"
-	testing "k8s.io/client-go/testing"
-)
-
-// FakeMachines implements MachineInterface
-type FakeMachines struct {
-	Fake *FakeMachineV1alpha1
-}
-
-var machinesResource = schema.GroupVersionResource{Group: "machine.k8s.io", Version: "v1alpha1", Resource: "machines"}
-
-var machinesKind = schema.GroupVersionKind{Group: "machine.k8s.io", Version: "v1alpha1", Kind: "Machine"}
-
-// Get takes name of the machine, and returns the corresponding machine object, and an error if there is any.
-func (c *FakeMachines) Get(name string, options v1.GetOptions) (result *v1alpha1.Machine, err error) {
-	obj, err := c.Fake.
-		Invokes(testing.NewRootGetAction(machinesResource, name), &v1alpha1.Machine{})
-	if obj == nil {
-		return nil, err
-	}
-	return obj.(*v1alpha1.Machine), err
-}
-
-// List takes label and field selectors, and returns the list of Machines that match those selectors.
-func (c *FakeMachines) List(opts v1.ListOptions) (result *v1alpha1.MachineList, err error) {
-	obj, err := c.Fake.
-		Invokes(testing.NewRootListAction(machinesResource, machinesKind, opts), &v1alpha1.MachineList{})
-	if obj == nil {
-		return nil, err
-	}
-
-	label, _, _ := testing.ExtractFromListOptions(opts)
-	if label == nil {
-		label = labels.Everything()
-	}
-	list := &v1alpha1.MachineList{ListMeta: obj.(*v1alpha1.MachineList).ListMeta}
-	for _, item := range obj.(*v1alpha1.MachineList).Items {
-		if label.Matches(labels.Set(item.Labels)) {
-			list.Items = append(list.Items, item)
-		}
-	}
-	return list, err
-}
-
-// Watch returns a watch.Interface that watches the requested machines.
-func (c *FakeMachines) Watch(opts v1.ListOptions) (watch.Interface, error) {
-	return c.Fake.
-		InvokesWatch(testing.NewRootWatchAction(machinesResource, opts))
-}
-
-// Create takes the representation of a machine and creates it.  Returns the server's representation of the machine, and an error, if there is any.
-func (c *FakeMachines) Create(machine *v1alpha1.Machine) (result *v1alpha1.Machine, err error) {
-	obj, err := c.Fake.
-		Invokes(testing.NewRootCreateAction(machinesResource, machine), &v1alpha1.Machine{})
-	if obj == nil {
-		return nil, err
-	}
-	return obj.(*v1alpha1.Machine), err
-}
-
-// Update takes the representation of a machine and updates it. Returns the server's representation of the machine, and an error, if there is any.
-func (c *FakeMachines) Update(machine *v1alpha1.Machine) (result *v1alpha1.Machine, err error) {
-	obj, err := c.Fake.
-		Invokes(testing.NewRootUpdateAction(machinesResource, machine), &v1alpha1.Machine{})
-	if obj == nil {
-		return nil, err
-	}
-	return obj.(*v1alpha1.Machine), err
-}
-
-// UpdateStatus was generated because the type contains a Status member.
-// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
-func (c *FakeMachines) UpdateStatus(machine *v1alpha1.Machine) (*v1alpha1.Machine, error) {
-	obj, err := c.Fake.
-		Invokes(testing.NewRootUpdateSubresourceAction(machinesResource, "status", machine), &v1alpha1.Machine{})
-	if obj == nil {
-		return nil, err
-	}
-	return obj.(*v1alpha1.Machine), err
-}
-
-// Delete takes name of the machine and deletes it. Returns an error if one occurs.
-func (c *FakeMachines) Delete(name string, options *v1.DeleteOptions) error {
-	_, err := c.Fake.
-		Invokes(testing.NewRootDeleteAction(machinesResource, name), &v1alpha1.Machine{})
-	return err
-}
-
-// DeleteCollection deletes a collection of objects.
-func (c *FakeMachines) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
-	action := testing.NewRootDeleteCollectionAction(machinesResource, listOptions)
-
-	_, err := c.Fake.Invokes(action, &v1alpha1.MachineList{})
-	return err
-}
-
-// Patch applies the patch and returns the patched machine.
-func (c *FakeMachines) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Machine, err error) {
-	obj, err := c.Fake.
-		Invokes(testing.NewRootPatchSubresourceAction(machinesResource, name, pt, data, subresources...), &v1alpha1.Machine{})
-	if obj == nil {
-		return nil, err
-	}
-	return obj.(*v1alpha1.Machine), err
-}
diff --git a/pkg/client/clientset/versioned/typed/machines/v1alpha1/fake/fake_machines_client.go b/pkg/client/clientset/versioned/typed/machines/v1alpha1/fake/fake_machines_client.go
deleted file mode 100644
index ff954c8c..00000000
--- a/pkg/client/clientset/versioned/typed/machines/v1alpha1/fake/fake_machines_client.go
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package fake
-
-import (
-	v1alpha1 "github.com/kubermatic/machine-controller/pkg/client/clientset/versioned/typed/machines/v1alpha1"
-	rest "k8s.io/client-go/rest"
-	testing "k8s.io/client-go/testing"
-)
-
-type FakeMachineV1alpha1 struct {
-	*testing.Fake
-}
-
-func (c *FakeMachineV1alpha1) Machines() v1alpha1.MachineInterface {
-	return &FakeMachines{c}
-}
-
-// RESTClient returns a RESTClient that is used to communicate
-// with API server by this client implementation.
-func (c *FakeMachineV1alpha1) RESTClient() rest.Interface {
-	var ret *rest.RESTClient
-	return ret
-}
diff --git a/pkg/client/clientset/versioned/typed/machines/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/machines/v1alpha1/generated_expansion.go
deleted file mode 100644
index 9f284825..00000000
--- a/pkg/client/clientset/versioned/typed/machines/v1alpha1/generated_expansion.go
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package v1alpha1
-
-type MachineExpansion interface{}
diff --git a/pkg/client/clientset/versioned/typed/machines/v1alpha1/machine.go b/pkg/client/clientset/versioned/typed/machines/v1alpha1/machine.go
deleted file mode 100644
index 154be2e4..00000000
--- a/pkg/client/clientset/versioned/typed/machines/v1alpha1/machine.go
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
-	"time"
-
-	scheme "github.com/kubermatic/machine-controller/pkg/client/clientset/versioned/scheme"
-	v1alpha1 "github.com/kubermatic/machine-controller/pkg/machines/v1alpha1"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	types "k8s.io/apimachinery/pkg/types"
-	watch "k8s.io/apimachinery/pkg/watch"
-	rest "k8s.io/client-go/rest"
-)
-
-// MachinesGetter has a method to return a MachineInterface.
-// A group's client should implement this interface.
-type MachinesGetter interface {
-	Machines() MachineInterface
-}
-
-// MachineInterface has methods to work with Machine resources.
-type MachineInterface interface {
-	Create(*v1alpha1.Machine) (*v1alpha1.Machine, error)
-	Update(*v1alpha1.Machine) (*v1alpha1.Machine, error)
-	UpdateStatus(*v1alpha1.Machine) (*v1alpha1.Machine, error)
-	Delete(name string, options *v1.DeleteOptions) error
-	DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
-	Get(name string, options v1.GetOptions) (*v1alpha1.Machine, error)
-	List(opts v1.ListOptions) (*v1alpha1.MachineList, error)
-	Watch(opts v1.ListOptions) (watch.Interface, error)
-	Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Machine, err error)
-	MachineExpansion
-}
-
-// machines implements MachineInterface
-type machines struct {
-	client rest.Interface
-}
-
-// newMachines returns a Machines
-func newMachines(c *MachineV1alpha1Client) *machines {
-	return &machines{
-		client: c.RESTClient(),
-	}
-}
-
-// Get takes name of the machine, and returns the corresponding machine object, and an error if there is any.
-func (c *machines) Get(name string, options v1.GetOptions) (result *v1alpha1.Machine, err error) {
-	result = &v1alpha1.Machine{}
-	err = c.client.Get().
-		Resource("machines").
-		Name(name).
-		VersionedParams(&options, scheme.ParameterCodec).
-		Do().
-		Into(result)
-	return
-}
-
-// List takes label and field selectors, and returns the list of Machines that match those selectors.
-func (c *machines) List(opts v1.ListOptions) (result *v1alpha1.MachineList, err error) {
-	var timeout time.Duration
-	if opts.TimeoutSeconds != nil {
-		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
-	}
-	result = &v1alpha1.MachineList{}
-	err = c.client.Get().
-		Resource("machines").
-		VersionedParams(&opts, scheme.ParameterCodec).
-		Timeout(timeout).
-		Do().
-		Into(result)
-	return
-}
-
-// Watch returns a watch.Interface that watches the requested machines.
-func (c *machines) Watch(opts v1.ListOptions) (watch.Interface, error) {
-	var timeout time.Duration
-	if opts.TimeoutSeconds != nil {
-		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
-	}
-	opts.Watch = true
-	return c.client.Get().
-		Resource("machines").
-		VersionedParams(&opts, scheme.ParameterCodec).
-		Timeout(timeout).
-		Watch()
-}
-
-// Create takes the representation of a machine and creates it.  Returns the server's representation of the machine, and an error, if there is any.
-func (c *machines) Create(machine *v1alpha1.Machine) (result *v1alpha1.Machine, err error) {
-	result = &v1alpha1.Machine{}
-	err = c.client.Post().
-		Resource("machines").
-		Body(machine).
-		Do().
-		Into(result)
-	return
-}
-
-// Update takes the representation of a machine and updates it. Returns the server's representation of the machine, and an error, if there is any.
-func (c *machines) Update(machine *v1alpha1.Machine) (result *v1alpha1.Machine, err error) {
-	result = &v1alpha1.Machine{}
-	err = c.client.Put().
-		Resource("machines").
-		Name(machine.Name).
-		Body(machine).
-		Do().
-		Into(result)
-	return
-}
-
-// UpdateStatus was generated because the type contains a Status member.
-// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
-
-func (c *machines) UpdateStatus(machine *v1alpha1.Machine) (result *v1alpha1.Machine, err error) {
-	result = &v1alpha1.Machine{}
-	err = c.client.Put().
-		Resource("machines").
-		Name(machine.Name).
-		SubResource("status").
-		Body(machine).
-		Do().
-		Into(result)
-	return
-}
-
-// Delete takes name of the machine and deletes it. Returns an error if one occurs.
-func (c *machines) Delete(name string, options *v1.DeleteOptions) error {
-	return c.client.Delete().
-		Resource("machines").
-		Name(name).
-		Body(options).
-		Do().
-		Error()
-}
-
-// DeleteCollection deletes a collection of objects.
-func (c *machines) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
-	var timeout time.Duration
-	if listOptions.TimeoutSeconds != nil {
-		timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
-	}
-	return c.client.Delete().
-		Resource("machines").
-		VersionedParams(&listOptions, scheme.ParameterCodec).
-		Timeout(timeout).
-		Body(options).
-		Do().
-		Error()
-}
-
-// Patch applies the patch and returns the patched machine.
-func (c *machines) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Machine, err error) {
-	result = &v1alpha1.Machine{}
-	err = c.client.Patch(pt).
-		Resource("machines").
-		SubResource(subresources...).
-		Name(name).
-		Body(data).
-		Do().
-		Into(result)
-	return
-}
diff --git a/pkg/client/clientset/versioned/typed/machines/v1alpha1/machines_client.go b/pkg/client/clientset/versioned/typed/machines/v1alpha1/machines_client.go
deleted file mode 100644
index a5a51224..00000000
--- a/pkg/client/clientset/versioned/typed/machines/v1alpha1/machines_client.go
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
-	"github.com/kubermatic/machine-controller/pkg/client/clientset/versioned/scheme"
-	v1alpha1 "github.com/kubermatic/machine-controller/pkg/machines/v1alpha1"
-	rest "k8s.io/client-go/rest"
-)
-
-type MachineV1alpha1Interface interface {
-	RESTClient() rest.Interface
-	MachinesGetter
-}
-
-// MachineV1alpha1Client is used to interact with features provided by the machine.k8s.io group.
-type MachineV1alpha1Client struct {
-	restClient rest.Interface
-}
-
-func (c *MachineV1alpha1Client) Machines() MachineInterface {
-	return newMachines(c)
-}
-
-// NewForConfig creates a new MachineV1alpha1Client for the given config.
-func NewForConfig(c *rest.Config) (*MachineV1alpha1Client, error) {
-	config := *c
-	if err := setConfigDefaults(&config); err != nil {
-		return nil, err
-	}
-	client, err := rest.RESTClientFor(&config)
-	if err != nil {
-		return nil, err
-	}
-	return &MachineV1alpha1Client{client}, nil
-}
-
-// NewForConfigOrDie creates a new MachineV1alpha1Client for the given config and
-// panics if there is an error in the config.
-func NewForConfigOrDie(c *rest.Config) *MachineV1alpha1Client {
-	client, err := NewForConfig(c)
-	if err != nil {
-		panic(err)
-	}
-	return client
-}
-
-// New creates a new MachineV1alpha1Client for the given RESTClient.
-func New(c rest.Interface) *MachineV1alpha1Client {
-	return &MachineV1alpha1Client{c}
-}
-
-func setConfigDefaults(config *rest.Config) error {
-	gv := v1alpha1.SchemeGroupVersion
-	config.GroupVersion = &gv
-	config.APIPath = "/apis"
-	config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
-
-	if config.UserAgent == "" {
-		config.UserAgent = rest.DefaultKubernetesUserAgent()
-	}
-
-	return nil
-}
-
-// RESTClient returns a RESTClient that is used to communicate
-// with API server by this client implementation.
-func (c *MachineV1alpha1Client) RESTClient() rest.Interface {
-	if c == nil {
-		return nil
-	}
-	return c.restClient
-}
diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go
deleted file mode 100644
index 569774b9..00000000
--- a/pkg/client/informers/externalversions/factory.go
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by informer-gen. DO NOT EDIT.
-
-package externalversions
-
-import (
-	reflect "reflect"
-	sync "sync"
-	time "time"
-
-	versioned "github.com/kubermatic/machine-controller/pkg/client/clientset/versioned"
-	internalinterfaces "github.com/kubermatic/machine-controller/pkg/client/informers/externalversions/internalinterfaces"
-	machines "github.com/kubermatic/machine-controller/pkg/client/informers/externalversions/machines"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	runtime "k8s.io/apimachinery/pkg/runtime"
-	schema "k8s.io/apimachinery/pkg/runtime/schema"
-	cache "k8s.io/client-go/tools/cache"
-)
-
-// SharedInformerOption defines the functional option type for SharedInformerFactory.
-type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
-
-type sharedInformerFactory struct {
-	client           versioned.Interface
-	namespace        string
-	tweakListOptions internalinterfaces.TweakListOptionsFunc
-	lock             sync.Mutex
-	defaultResync    time.Duration
-	customResync     map[reflect.Type]time.Duration
-
-	informers map[reflect.Type]cache.SharedIndexInformer
-	// startedInformers is used for tracking which informers have been started.
-	// This allows Start() to be called multiple times safely.
-	startedInformers map[reflect.Type]bool
-}
-
-// WithCustomResyncConfig sets a custom resync period for the specified informer types.
-func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
-	return func(factory *sharedInformerFactory) *sharedInformerFactory {
-		for k, v := range resyncConfig {
-			factory.customResync[reflect.TypeOf(k)] = v
-		}
-		return factory
-	}
-}
-
-// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
-func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
-	return func(factory *sharedInformerFactory) *sharedInformerFactory {
-		factory.tweakListOptions = tweakListOptions
-		return factory
-	}
-}
-
-// WithNamespace limits the SharedInformerFactory to the specified namespace.
-func WithNamespace(namespace string) SharedInformerOption {
-	return func(factory *sharedInformerFactory) *sharedInformerFactory {
-		factory.namespace = namespace
-		return factory
-	}
-}
-
-// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
-func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
-	return NewSharedInformerFactoryWithOptions(client, defaultResync)
-}
-
-// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
-// Listers obtained via this SharedInformerFactory will be subject to the same filters
-// as specified here.
-// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
-func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
-	return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
-}
-
-// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
-func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
-	factory := &sharedInformerFactory{
-		client:           client,
-		namespace:        v1.NamespaceAll,
-		defaultResync:    defaultResync,
-		informers:        make(map[reflect.Type]cache.SharedIndexInformer),
-		startedInformers: make(map[reflect.Type]bool),
-		customResync:     make(map[reflect.Type]time.Duration),
-	}
-
-	// Apply all options
-	for _, opt := range options {
-		factory = opt(factory)
-	}
-
-	return factory
-}
-
-// Start initializes all requested informers.
-func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
-	f.lock.Lock()
-	defer f.lock.Unlock()
-
-	for informerType, informer := range f.informers {
-		if !f.startedInformers[informerType] {
-			go informer.Run(stopCh)
-			f.startedInformers[informerType] = true
-		}
-	}
-}
-
-// WaitForCacheSync waits for all started informers' cache were synced.
-func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
-	informers := func() map[reflect.Type]cache.SharedIndexInformer {
-		f.lock.Lock()
-		defer f.lock.Unlock()
-
-		informers := map[reflect.Type]cache.SharedIndexInformer{}
-		for informerType, informer := range f.informers {
-			if f.startedInformers[informerType] {
-				informers[informerType] = informer
-			}
-		}
-		return informers
-	}()
-
-	res := map[reflect.Type]bool{}
-	for informType, informer := range informers {
-		res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
-	}
-	return res
-}
-
-// InternalInformerFor returns the SharedIndexInformer for obj using an internal
-// client.
-func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
-	f.lock.Lock()
-	defer f.lock.Unlock()
-
-	informerType := reflect.TypeOf(obj)
-	informer, exists := f.informers[informerType]
-	if exists {
-		return informer
-	}
-
-	resyncPeriod, exists := f.customResync[informerType]
-	if !exists {
-		resyncPeriod = f.defaultResync
-	}
-
-	informer = newFunc(f.client, resyncPeriod)
-	f.informers[informerType] = informer
-
-	return informer
-}
-
-// SharedInformerFactory provides shared informers for resources in all known
-// API group versions.
-type SharedInformerFactory interface {
-	internalinterfaces.SharedInformerFactory
-	ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
-	WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
-
-	Machine() machines.Interface
-}
-
-func (f *sharedInformerFactory) Machine() machines.Interface {
-	return machines.New(f, f.namespace, f.tweakListOptions)
-}
diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go
deleted file mode 100644
index db336849..00000000
--- a/pkg/client/informers/externalversions/generic.go
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by informer-gen. DO NOT EDIT.
-
-package externalversions
-
-import (
-	"fmt"
-
-	v1alpha1 "github.com/kubermatic/machine-controller/pkg/machines/v1alpha1"
-	schema "k8s.io/apimachinery/pkg/runtime/schema"
-	cache "k8s.io/client-go/tools/cache"
-)
-
-// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
-// sharedInformers based on type
-type GenericInformer interface {
-	Informer() cache.SharedIndexInformer
-	Lister() cache.GenericLister
-}
-
-type genericInformer struct {
-	informer cache.SharedIndexInformer
-	resource schema.GroupResource
-}
-
-// Informer returns the SharedIndexInformer.
-func (f *genericInformer) Informer() cache.SharedIndexInformer {
-	return f.informer
-}
-
-// Lister returns the GenericLister.
-func (f *genericInformer) Lister() cache.GenericLister {
-	return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
-}
-
-// ForResource gives generic access to a shared informer of the matching type
-// TODO extend this to unknown resources with a client pool
-func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
-	switch resource {
-	// Group=machine.k8s.io, Version=v1alpha1
-	case v1alpha1.SchemeGroupVersion.WithResource("machines"):
-		return &genericInformer{resource: resource.GroupResource(), informer: f.Machine().V1alpha1().Machines().Informer()}, nil
-
-	}
-
-	return nil, fmt.Errorf("no informer found for %v", resource)
-}
diff --git a/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go
deleted file mode 100644
index 51bf0c6d..00000000
--- a/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by informer-gen. DO NOT EDIT.
-
-package internalinterfaces
-
-import (
-	time "time"
-
-	versioned "github.com/kubermatic/machine-controller/pkg/client/clientset/versioned"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	runtime "k8s.io/apimachinery/pkg/runtime"
-	cache "k8s.io/client-go/tools/cache"
-)
-
-// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.
-type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
-
-// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
-type SharedInformerFactory interface {
-	Start(stopCh <-chan struct{})
-	InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
-}
-
-// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
-type TweakListOptionsFunc func(*v1.ListOptions)
diff --git a/pkg/client/informers/externalversions/machines/interface.go b/pkg/client/informers/externalversions/machines/interface.go
deleted file mode 100644
index d5c6ddb0..00000000
--- a/pkg/client/informers/externalversions/machines/interface.go
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by informer-gen. DO NOT EDIT.
-
-package machine
-
-import (
-	internalinterfaces "github.com/kubermatic/machine-controller/pkg/client/informers/externalversions/internalinterfaces"
-	v1alpha1 "github.com/kubermatic/machine-controller/pkg/client/informers/externalversions/machines/v1alpha1"
-)
-
-// Interface provides access to each of this group's versions.
-type Interface interface {
-	// V1alpha1 provides access to shared informers for resources in V1alpha1.
-	V1alpha1() v1alpha1.Interface
-}
-
-type group struct {
-	factory          internalinterfaces.SharedInformerFactory
-	namespace        string
-	tweakListOptions internalinterfaces.TweakListOptionsFunc
-}
-
-// New returns a new Interface.
-func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
-	return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
-}
-
-// V1alpha1 returns a new v1alpha1.Interface.
-func (g *group) V1alpha1() v1alpha1.Interface {
-	return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
-}
diff --git a/pkg/client/informers/externalversions/machines/v1alpha1/interface.go b/pkg/client/informers/externalversions/machines/v1alpha1/interface.go
deleted file mode 100644
index 7e367e9f..00000000
--- a/pkg/client/informers/externalversions/machines/v1alpha1/interface.go
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by informer-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
-	internalinterfaces "github.com/kubermatic/machine-controller/pkg/client/informers/externalversions/internalinterfaces"
-)
-
-// Interface provides access to all the informers in this group version.
-type Interface interface {
-	// Machines returns a MachineInformer.
-	Machines() MachineInformer
-}
-
-type version struct {
-	factory          internalinterfaces.SharedInformerFactory
-	namespace        string
-	tweakListOptions internalinterfaces.TweakListOptionsFunc
-}
-
-// New returns a new Interface.
-func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
-	return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
-}
-
-// Machines returns a MachineInformer.
-func (v *version) Machines() MachineInformer {
-	return &machineInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
-}
diff --git a/pkg/client/informers/externalversions/machines/v1alpha1/machine.go b/pkg/client/informers/externalversions/machines/v1alpha1/machine.go
deleted file mode 100644
index f09bad83..00000000
--- a/pkg/client/informers/externalversions/machines/v1alpha1/machine.go
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by informer-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
-	time "time"
-
-	versioned "github.com/kubermatic/machine-controller/pkg/client/clientset/versioned"
-	internalinterfaces "github.com/kubermatic/machine-controller/pkg/client/informers/externalversions/internalinterfaces"
-	v1alpha1 "github.com/kubermatic/machine-controller/pkg/client/listers/machines/v1alpha1"
-	machinesv1alpha1 "github.com/kubermatic/machine-controller/pkg/machines/v1alpha1"
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	runtime "k8s.io/apimachinery/pkg/runtime"
-	watch "k8s.io/apimachinery/pkg/watch"
-	cache "k8s.io/client-go/tools/cache"
-)
-
-// MachineInformer provides access to a shared informer and lister for
-// Machines.
-type MachineInformer interface {
-	Informer() cache.SharedIndexInformer
-	Lister() v1alpha1.MachineLister
-}
-
-type machineInformer struct {
-	factory          internalinterfaces.SharedInformerFactory
-	tweakListOptions internalinterfaces.TweakListOptionsFunc
-}
-
-// NewMachineInformer constructs a new informer for Machine type.
-// Always prefer using an informer factory to get a shared informer instead of getting an independent
-// one. This reduces memory footprint and number of connections to the server.
-func NewMachineInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
-	return NewFilteredMachineInformer(client, resyncPeriod, indexers, nil)
-}
-
-// NewFilteredMachineInformer constructs a new informer for Machine type.
-// Always prefer using an informer factory to get a shared informer instead of getting an independent
-// one. This reduces memory footprint and number of connections to the server.
-func NewFilteredMachineInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
-	return cache.NewSharedIndexInformer(
-		&cache.ListWatch{
-			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
-				if tweakListOptions != nil {
-					tweakListOptions(&options)
-				}
-				return client.MachineV1alpha1().Machines().List(options)
-			},
-			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
-				if tweakListOptions != nil {
-					tweakListOptions(&options)
-				}
-				return client.MachineV1alpha1().Machines().Watch(options)
-			},
-		},
-		&machinesv1alpha1.Machine{},
-		resyncPeriod,
-		indexers,
-	)
-}
-
-func (f *machineInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
-	return NewFilteredMachineInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
-}
-
-func (f *machineInformer) Informer() cache.SharedIndexInformer {
-	return f.factory.InformerFor(&machinesv1alpha1.Machine{}, f.defaultInformer)
-}
-
-func (f *machineInformer) Lister() v1alpha1.MachineLister {
-	return v1alpha1.NewMachineLister(f.Informer().GetIndexer())
-}
diff --git a/pkg/client/listers/machines/v1alpha1/expansion_generated.go b/pkg/client/listers/machines/v1alpha1/expansion_generated.go
deleted file mode 100644
index 34631b3c..00000000
--- a/pkg/client/listers/machines/v1alpha1/expansion_generated.go
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by lister-gen. DO NOT EDIT.
-
-package v1alpha1
-
-// MachineListerExpansion allows custom methods to be added to
-// MachineLister.
-type MachineListerExpansion interface{}
diff --git a/pkg/client/listers/machines/v1alpha1/machine.go b/pkg/client/listers/machines/v1alpha1/machine.go
deleted file mode 100644
index b2829094..00000000
--- a/pkg/client/listers/machines/v1alpha1/machine.go
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Copyright 2017 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by lister-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
-	v1alpha1 "github.com/kubermatic/machine-controller/pkg/machines/v1alpha1"
-	"k8s.io/apimachinery/pkg/api/errors"
-	"k8s.io/apimachinery/pkg/labels"
-	"k8s.io/client-go/tools/cache"
-)
-
-// MachineLister helps list Machines.
-type MachineLister interface {
-	// List lists all Machines in the indexer.
-	List(selector labels.Selector) (ret []*v1alpha1.Machine, err error)
-	// Get retrieves the Machine from the index for a given name.
-	Get(name string) (*v1alpha1.Machine, error)
-	MachineListerExpansion
-}
-
-// machineLister implements the MachineLister interface.
-type machineLister struct {
-	indexer cache.Indexer
-}
-
-// NewMachineLister returns a new MachineLister.
-func NewMachineLister(indexer cache.Indexer) MachineLister {
-	return &machineLister{indexer: indexer}
-}
-
-// List lists all Machines in the indexer.
-func (s *machineLister) List(selector labels.Selector) (ret []*v1alpha1.Machine, err error) {
-	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
-		ret = append(ret, m.(*v1alpha1.Machine))
-	})
-	return ret, err
-}
-
-// Get retrieves the Machine from the index for a given name.
-func (s *machineLister) Get(name string) (*v1alpha1.Machine, error) {
-	obj, exists, err := s.indexer.GetByKey(name)
-	if err != nil {
-		return nil, err
-	}
-	if !exists {
-		return nil, errors.NewNotFound(v1alpha1.Resource("machine"), name)
-	}
-	return obj.(*v1alpha1.Machine), nil
-}
diff --git a/pkg/cloudprovider/provider/packet/provider.go b/pkg/cloudprovider/provider/packet/provider.go
index 75f6e023..e24d9779 100644
--- a/pkg/cloudprovider/provider/packet/provider.go
+++ b/pkg/cloudprovider/provider/packet/provider.go
@@ -429,6 +429,8 @@ func getNameForOS(os providerconfigtypes.OperatingSystem) (string, error) {
 		return "centos_7", nil
 	case providerconfigtypes.OperatingSystemCoreos:
 		return "coreos_stable", nil
+	case providerconfigtypes.OperatingSystemFlatcar:
+		return "flatcar_stable", nil
 	}
 	return "", providerconfigtypes.ErrOSNotSupported
 }
diff --git a/pkg/controller/machine/machine.go b/pkg/controller/machine/machine.go
index 12620d19..25cdeecb 100644
--- a/pkg/controller/machine/machine.go
+++ b/pkg/controller/machine/machine.go
@@ -124,8 +124,10 @@ type NodeSettings struct {
 	RegistryMirrors []string
 	// Translates to --pod-infra-container-image on the kubelet. If not set, the kubelet will default it.
 	PauseImage string
-	// The hyperkube image to use. Currently only Container Linux uses it.
+	// The hyperkube image to use. Currently only Container Linux and Flatcar Linux uses it.
 	HyperkubeImage string
+	// The kubelet repository to use. Currently only Flatcar Linux uses it.
+	KubeletRepository string
 }
 
 type KubeconfigProvider interface {
@@ -606,19 +608,42 @@ func (r *Reconciler) deleteCloudProviderInstance(prov cloudprovidertypes.Provide
 }
 
 func (r *Reconciler) deleteNodeForMachine(machine *clusterv1alpha1.Machine) error {
-	selector, err := labels.Parse(NodeOwnerLabelName + "=" + string(machine.UID))
-	if err != nil {
-		return fmt.Errorf("failed to parse label selector: %v", err)
-	}
-	listOpts := &ctrlruntimeclient.ListOptions{LabelSelector: selector}
-	nodes := &corev1.NodeList{}
-	if err := r.client.List(r.ctx, nodes, listOpts); err != nil {
-		return fmt.Errorf("failed to list nodes: %v", err)
-	}
+	// If there's NodeRef on the Machine object, remove the Node by using the
+	// value of the NodeRef. If there's no NodeRef, try to find the Node by
+	// listing nodes using the NodeOwner label selector.
+	if machine.Status.NodeRef != nil {
+		objKey := ctrlruntimeclient.ObjectKey{Name: machine.Status.NodeRef.Name}
+		node := &corev1.Node{}
+		if err := r.client.Get(r.ctx, objKey, node); err != nil {
+			return fmt.Errorf("failed to get node %s: %v", machine.Status.NodeRef.Name, err)
+		}
+
+		if err := r.client.Delete(r.ctx, node); err != nil {
+			if !kerrors.IsNotFound(err) {
+				return err
+			}
+			klog.V(2).Infof("node %q does not longer exist for machine %q", machine.Status.NodeRef.Name, machine.Spec.Name)
+		}
+	} else {
+		selector, err := labels.Parse(NodeOwnerLabelName + "=" + string(machine.UID))
+		if err != nil {
+			return fmt.Errorf("failed to parse label selector: %v", err)
+		}
+		listOpts := &ctrlruntimeclient.ListOptions{LabelSelector: selector}
+		nodes := &corev1.NodeList{}
+		if err := r.client.List(r.ctx, nodes, listOpts); err != nil {
+			return fmt.Errorf("failed to list nodes: %v", err)
+		}
+		if len(nodes.Items) == 0 {
+			// We just want log that we didn't found the node. We don't want to
+			// return here, as we want to remove finalizers at the end.
+			klog.V(3).Infof("No node found for the machine %s", machine.Spec.Name)
+		}
 
-	for _, node := range nodes.Items {
-		if err := r.client.Delete(r.ctx, &node); err != nil {
-			return err
+		for _, node := range nodes.Items {
+			if err := r.client.Delete(r.ctx, &node); err != nil {
+				return err
+			}
 		}
 	}
 
@@ -666,6 +691,7 @@ func (r *Reconciler) ensureInstanceExistsForMachine(
 				RegistryMirrors:       r.nodeSettings.RegistryMirrors,
 				PauseImage:            r.nodeSettings.PauseImage,
 				HyperkubeImage:        r.nodeSettings.HyperkubeImage,
+				KubeletRepository:     r.nodeSettings.KubeletRepository,
 				NoProxy:               r.nodeSettings.NoProxy,
 				HTTPProxy:             r.nodeSettings.HTTPProxy,
 			}
@@ -885,8 +911,31 @@ func (r *Reconciler) getNode(instance instance.Instance, provider providerconfig
 				return node.DeepCopy(), true, nil
 			}
 		}
+		// If we were unable to find Node by ProviderID, fallback to IP address matching.
+		// This usually happens if there's no CCM deployed in the cluster.
+		//
+		// This mechanism is not always reliable, as providers reuse the IP addresses after
+		// some time.
+		//
+		// If we rollout a Machine, it can happen that a new instance has the same
+		// IP addresses as the instance that has just been deleted. If machine-controller
+		// processes the new Machine before removing the old Machine and the corresponding
+		// Node object, machine-controller could update the NodeOwner label on the old Node
+		// object to point to the Machine that just got created, as IP addresses would match.
+		// This causes machine-controller to fail to delete the old Node object, which could
+		// then cause cluster stability issues in some cases.
 		for _, nodeAddress := range node.Status.Addresses {
 			for instanceAddress := range instance.Addresses() {
+				// We observed that the issue described above happens often on Hetzner.
+				// As we know that the Node and the instance name will always be same
+				// on Hetzner, we can use it as an additional check to prevent this
+				// issue.
+				// TODO: We should do this for other providers, but there are providers where
+				// the node and the instance names will not match, so it requires further
+				// investigation (e.g. AWS).
+				if provider == providerconfigtypes.CloudProviderHetzner && node.Name != instance.Name() {
+					continue
+				}
 				if nodeAddress.Address == instanceAddress {
 					return node.DeepCopy(), true, nil
 				}
diff --git a/pkg/userdata/centos/provider.go b/pkg/userdata/centos/provider.go
index 6ed072c9..36a67e6a 100644
--- a/pkg/userdata/centos/provider.go
+++ b/pkg/userdata/centos/provider.go
@@ -315,5 +315,5 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
 `
diff --git a/pkg/userdata/flatcar/provider.go b/pkg/userdata/flatcar/provider.go
index ee7ceaa7..0d991670 100644
--- a/pkg/userdata/flatcar/provider.go
+++ b/pkg/userdata/flatcar/provider.go
@@ -23,7 +23,6 @@ package flatcar
 import (
 	"bytes"
 	"fmt"
-	"strings"
 	"text/template"
 
 	"github.com/Masterminds/semver"
@@ -33,12 +32,15 @@ import (
 	userdatahelper "github.com/kubermatic/machine-controller/pkg/userdata/helper"
 )
 
+const (
+	lessThen118Check = "< 1.18"
+)
+
 // Provider is a pkg/userdata/plugin.Provider implementation.
 type Provider struct{}
 
 // UserData renders user-data template to string.
 func (p Provider) UserData(req plugin.UserDataRequest) (string, error) {
-
 	tmpl, err := template.New("user-data").Funcs(userdatahelper.TxtFuncMap()).Parse(userDataTemplate)
 	if err != nil {
 		return "", fmt.Errorf("failed to parse user-data template: %v", err)
@@ -73,37 +75,40 @@ func (p Provider) UserData(req plugin.UserDataRequest) (string, error) {
 		return "", fmt.Errorf("error extracting cacert: %v", err)
 	}
 
-	// We need to reconfigure rkt to allow insecure registries in case the hyperkube image comes from an insecure registry
-	var insecureHyperkubeImage bool
-	for _, registry := range req.InsecureRegistries {
-		if strings.Contains(req.HyperkubeImage, registry) {
-			insecureHyperkubeImage = true
-		}
-	}
-
 	if flatcarConfig.DisableAutoUpdate {
 		flatcarConfig.DisableLocksmithD = true
 		flatcarConfig.DisableUpdateEngine = true
 	}
 
+	kubeletImage := req.KubeletRepository
+	lessThen118, err := semver.NewConstraint(lessThen118Check)
+	if err != nil {
+		return "", err
+	}
+
+	if lessThen118.Check(kubeletVersion) {
+		kubeletImage = req.HyperkubeImage
+	}
+	kubeletImage = kubeletImage + ":v" + kubeletVersion.String()
+
 	data := struct {
 		plugin.UserDataRequest
-		ProviderSpec           *providerconfigtypes.Config
-		FlatcarConfig          *Config
-		Kubeconfig             string
-		KubernetesCACert       string
-		KubeletVersion         string
-		InsecureHyperkubeImage bool
-		NodeIPScript           string
+		ProviderSpec     *providerconfigtypes.Config
+		FlatcarConfig    *Config
+		Kubeconfig       string
+		KubernetesCACert string
+		KubeletImage     string
+		KubeletVersion   string
+		NodeIPScript     string
 	}{
-		UserDataRequest:        req,
-		ProviderSpec:           pconfig,
-		FlatcarConfig:          flatcarConfig,
-		Kubeconfig:             kubeconfigString,
-		KubernetesCACert:       kubernetesCACert,
-		KubeletVersion:         kubeletVersion.String(),
-		InsecureHyperkubeImage: insecureHyperkubeImage,
-		NodeIPScript:           userdatahelper.SetupNodeIPEnvScript(),
+		UserDataRequest:  req,
+		ProviderSpec:     pconfig,
+		FlatcarConfig:    flatcarConfig,
+		Kubeconfig:       kubeconfigString,
+		KubernetesCACert: kubernetesCACert,
+		KubeletImage:     kubeletImage,
+		KubeletVersion:   kubeletVersion.String(),
+		NodeIPScript:     userdatahelper.SetupNodeIPEnvScript(),
 	}
 	b := &bytes.Buffer{}
 	err = tmpl.Execute(b, data)
@@ -164,7 +169,7 @@ systemd:
             Environment=ALL_PROXY={{ .HTTPProxy }}
 {{- end }}
 
-    - name: download-healthcheck-script.service
+    - name: download-script.service
       enabled: true
       contents: |
         [Unit]
@@ -183,8 +188,8 @@ systemd:
       - name: 40-docker.conf
         contents: |
           [Unit]
-          Requires=download-healthcheck-script.service
-          After=download-healthcheck-script.service
+          Requires=download-script.service
+          After=download-script.service
       contents: |
 {{ containerRuntimeHealthCheckSystemdUnit | indent 10 }}
 
@@ -194,8 +199,8 @@ systemd:
       - name: 40-docker.conf
         contents: |
           [Unit]
-          Requires=download-healthcheck-script.service
-          After=download-healthcheck-script.service
+          Requires=download-script.service
+          After=download-script.service
       contents: |
 {{ kubeletHealthCheckSystemdUnit | indent 10 }}
 
@@ -227,38 +232,42 @@ systemd:
         MemoryAccounting=true
         EnvironmentFile=-/etc/environment
         EnvironmentFile=/etc/kubernetes/nodeip.conf
-{{- if .HTTPProxy }}
-        Environment=KUBELET_IMAGE=docker://{{ .HyperkubeImage }}:v{{ .KubeletVersion }}
-{{- else }}
-        Environment=KUBELET_IMAGE=docker://k8s.gcr.io/hyperkube-amd64:v{{ .KubeletVersion }}
-{{- end }}
-        Environment="RKT_RUN_ARGS=--uuid-file-save=/var/cache/kubelet-pod.uuid \
-          --inherit-env \
-          --insecure-options=image{{if .InsecureHyperkubeImage }},http{{ end }} \
-          --volume=resolv,kind=host,source=/etc/resolv.conf \
-          --mount volume=resolv,target=/etc/resolv.conf \
-          --volume cni-bin,kind=host,source=/opt/cni/bin \
-          --mount volume=cni-bin,target=/opt/cni/bin \
-          --volume cni-conf,kind=host,source=/etc/cni/net.d \
-          --mount volume=cni-conf,target=/etc/cni/net.d \
-          --volume etc-kubernetes,kind=host,source=/etc/kubernetes \
-          --mount volume=etc-kubernetes,target=/etc/kubernetes \
-          --volume var-log,kind=host,source=/var/log \
-          --mount volume=var-log,target=/var/log \
-          --volume var-lib-calico,kind=host,source=/var/lib/calico \
-          --mount volume=var-lib-calico,target=/var/lib/calico"
+        Environment=PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/bin
         ExecStartPre=/bin/bash /opt/bin/setup_net_env.sh
         ExecStartPre=/bin/mkdir -p /var/lib/calico
         ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
         ExecStartPre=/bin/mkdir -p /etc/cni/net.d
         ExecStartPre=/bin/mkdir -p /opt/cni/bin
-        ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/cache/kubelet-pod.uuid
-        ExecStartPre=-/bin/rm -rf /var/lib/rkt/cas/tmp/
         ExecStartPre=/bin/bash /opt/load-kernel-modules.sh
-        ExecStart=/usr/lib/flatcar/kubelet-wrapper \
-{{ if semverCompare ">=1.17.0" .KubeletVersion }}{{ print "          kubelet \\\n" }}{{ end -}}
+        ExecStartPre=/bin/sh -c '/usr/bin/env > /tmp/environment'
+        ExecStart=/usr/bin/docker run --name %n \
+          --rm --tty --restart no \
+          --network host \
+          --pid host \
+          --env-file /tmp/environment \
+          --privileged \
+          --cgroup-parent system.slice \
+          --entrypoint kubelet \
+          -v /dev:/dev \
+          -v /etc/cni/net.d:/etc/cni/net.d \
+          -v /etc/kubernetes:/etc/kubernetes \
+          -v /etc/machine-id:/etc/machine-id:ro \
+          -v /etc/os-release:/etc/os-release:ro \
+          -v /etc/resolv.conf:/etc/resolv.conf:ro \
+          -v /lib/modules:/lib/modules \
+          -v /mnt:/mnt:rshared \
+          -v /opt/cni/bin:/opt/cni/bin:ro \
+          -v /run:/run \
+          -v /sys:/sys \
+          -v /usr/sbin/iscsiadm:/usr/sbin/iscsiadm \
+          -v /var/lib/calico:/var/lib/calico:ro \
+          -v /var/lib/cni:/var/lib/cni \
+          -v /var/lib/docker:/var/lib/docker \
+          -v /var/lib/kubelet:/var/lib/kubelet:rshared \
+          -v /var/log/pods:/var/log/pods \
+          {{ .KubeletImage }} \
 {{ kubeletFlags .KubeletVersion .CloudProviderName .MachineSpec.Name .DNSIPs .ExternalCloudProvider .PauseImage .MachineSpec.Taints | indent 10 }}
-        ExecStop=-/usr/bin/rkt stop --uuid-file=/var/cache/kubelet-pod.uuid
+        ExecStop=-/usr/bin/docker stop %n
         Restart=always
         RestartSec=10
         [Install]
@@ -400,4 +409,6 @@ storage:
         inline: |
           #!/bin/bash
           set -xeuo pipefail
-{{ safeDownloadBinariesScript .KubeletVersion | indent 10 }}`
+{{ safeDownloadBinariesScript .KubeletVersion | indent 10 }}
+          systemctl disable download-script.service
+`
diff --git a/pkg/userdata/rhel/provider.go b/pkg/userdata/rhel/provider.go
index 10bcc69c..b0ba746f 100644
--- a/pkg/userdata/rhel/provider.go
+++ b/pkg/userdata/rhel/provider.go
@@ -325,5 +325,5 @@ rh_subscription:
 {{- end }}
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
 `
diff --git a/pkg/userdata/sles/provider.go b/pkg/userdata/sles/provider.go
index f2d00412..34fa5b11 100644
--- a/pkg/userdata/sles/provider.go
+++ b/pkg/userdata/sles/provider.go
@@ -270,5 +270,5 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
 `
diff --git a/pkg/userdata/ubuntu/provider.go b/pkg/userdata/ubuntu/provider.go
index af4ba7be..4186b1ad 100644
--- a/pkg/userdata/ubuntu/provider.go
+++ b/pkg/userdata/ubuntu/provider.go
@@ -383,5 +383,5 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
 `


Test patch:
diff --git a/pkg/controller/machine/machine_test.go b/pkg/controller/machine/machine_test.go
index 42661ba0..24ba69cd 100644
--- a/pkg/controller/machine/machine_test.go
+++ b/pkg/controller/machine/machine_test.go
@@ -26,6 +26,7 @@ import (
 
 	clusterv1alpha1 "github.com/kubermatic/machine-controller/pkg/apis/cluster/v1alpha1"
 	"github.com/kubermatic/machine-controller/pkg/cloudprovider/instance"
+	cloudprovidertypes "github.com/kubermatic/machine-controller/pkg/cloudprovider/types"
 	providerconfigtypes "github.com/kubermatic/machine-controller/pkg/providerconfig/types"
 
 	corev1 "k8s.io/api/core/v1"
@@ -36,6 +37,7 @@ import (
 	"k8s.io/client-go/kubernetes/scheme"
 	"k8s.io/client-go/tools/record"
 	"k8s.io/klog"
+	ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client"
 	ctrlruntimefake "sigs.k8s.io/controller-runtime/pkg/client/fake"
 )
 
@@ -99,7 +101,8 @@ func TestController_GetNode(t *testing.T) {
 	node1 := getTestNode("1", "aws")
 	node2 := getTestNode("2", "openstack")
 	node3 := getTestNode("3", "")
-	nodeList := []*corev1.Node{&node1, &node2, &node3}
+	node4 := getTestNode("4", "hetzner")
+	nodeList := []*corev1.Node{&node1, &node2, &node3, &node4}
 
 	tests := []struct {
 		name     string
@@ -149,6 +152,38 @@ func TestController_GetNode(t *testing.T) {
 			err:      nil,
 			instance: &fakeInstance{id: "3", addresses: map[string]corev1.NodeAddressType{"172.16.1.3": corev1.NodeInternalIP}},
 		},
+		{
+			name:     "hetzner node found by internal ip",
+			provider: "hetzner",
+			resNode:  &node3,
+			exists:   true,
+			err:      nil,
+			instance: &fakeInstance{id: "3", name: "node3", addresses: map[string]corev1.NodeAddressType{"192.168.1.3": corev1.NodeInternalIP}},
+		},
+		{
+			name:     "hetzner node found by external ip",
+			provider: "hetzner",
+			resNode:  &node3,
+			exists:   true,
+			err:      nil,
+			instance: &fakeInstance{id: "3", name: "node3", addresses: map[string]corev1.NodeAddressType{"172.16.1.3": corev1.NodeExternalIP}},
+		},
+		{
+			name:     "hetzner node not found - node and instance names mismatch",
+			provider: "hetzner",
+			resNode:  nil,
+			exists:   false,
+			err:      nil,
+			instance: &fakeInstance{id: "3", name: "instance3", addresses: map[string]corev1.NodeAddressType{"192.168.1.3": corev1.NodeInternalIP}},
+		},
+		{
+			name:     "hetzner node found by provider id",
+			provider: "hetzner",
+			resNode:  &node4,
+			exists:   true,
+			err:      nil,
+			instance: &fakeInstance{id: "4", addresses: map[string]corev1.NodeAddressType{"": ""}},
+		},
 	}
 
 	for _, test := range tests {
@@ -427,3 +462,137 @@ func TestControllerShouldEvict(t *testing.T) {
 		})
 	}
 }
+
+func TestControllerDeleteNodeForMachine(t *testing.T) {
+	machineUID := types.UID("test-1")
+
+	tests := []struct {
+		name             string
+		machine          *clusterv1alpha1.Machine
+		nodes            []runtime.Object
+		err              error
+		shouldDeleteNode string
+	}{
+		{
+			name: "delete node by nodeRef",
+			machine: &clusterv1alpha1.Machine{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:       "machine-1",
+					Finalizers: []string{"machine-node-delete-finalizer"},
+				},
+				Status: clusterv1alpha1.MachineStatus{
+					NodeRef: &corev1.ObjectReference{Name: "node-1"},
+				},
+			},
+			nodes: []runtime.Object{&corev1.Node{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "node-0",
+				}}, &corev1.Node{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "node-1",
+				}},
+			},
+			err:              nil,
+			shouldDeleteNode: "node-1",
+		},
+		{
+			name: "delete node by NodeOwner label",
+			machine: &clusterv1alpha1.Machine{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:       "machine-1",
+					Finalizers: []string{"machine-node-delete-finalizer"},
+					UID:        machineUID,
+				},
+				Status: clusterv1alpha1.MachineStatus{},
+			},
+			nodes: []runtime.Object{
+				&corev1.Node{
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "node-0",
+						Labels: map[string]string{
+							NodeOwnerLabelName: string(machineUID),
+						},
+					},
+				},
+				&corev1.Node{
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "node-1",
+					},
+				},
+			},
+			err:              nil,
+			shouldDeleteNode: "node-0",
+		},
+		{
+			name: "no node should be deleted",
+			machine: &clusterv1alpha1.Machine{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:       "machine-1",
+					Finalizers: []string{"machine-node-delete-finalizer"},
+					UID:        machineUID,
+				},
+				Status: clusterv1alpha1.MachineStatus{},
+			},
+			nodes: []runtime.Object{
+				&corev1.Node{
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "node-0",
+					},
+				},
+				&corev1.Node{
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "node-1",
+					},
+				},
+			},
+			err:              nil,
+			shouldDeleteNode: "",
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			objects := []runtime.Object{test.machine}
+			objects = append(objects, test.nodes...)
+
+			client := ctrlruntimefake.NewFakeClient(objects...)
+
+			ctx := context.TODO()
+			providerData := &cloudprovidertypes.ProviderData{
+				Ctx:    ctx,
+				Update: cloudprovidertypes.GetMachineUpdater(ctx, client),
+				Client: client,
+			}
+
+			reconciler := &Reconciler{
+				client:       client,
+				recorder:     &record.FakeRecorder{},
+				providerData: providerData,
+			}
+
+			err := reconciler.deleteNodeForMachine(test.machine)
+			if diff := deep.Equal(err, test.err); diff != nil {
+				t.Errorf("expected to get %v instead got: %v", test.err, err)
+			}
+			if err != nil {
+				return
+			}
+
+			if test.shouldDeleteNode != "" {
+				err = client.Get(ctx, types.NamespacedName{Name: test.shouldDeleteNode}, &corev1.Node{})
+				if !kerrors.IsNotFound(err) {
+					t.Errorf("expected node %q to be deleted, but got: %v", test.shouldDeleteNode, err)
+				}
+			} else {
+				nodes := &corev1.NodeList{}
+				err = client.List(ctx, nodes, &ctrlruntimeclient.ListOptions{})
+				if err != nil {
+					t.Errorf("error listing nodes: %v", err)
+				}
+				if len(test.nodes) != len(nodes.Items) {
+					t.Errorf("expected %d nodes, but got %d", len(test.nodes), len(nodes.Items))
+				}
+			}
+		})
+	}
+}
diff --git a/pkg/userdata/centos/testdata/kubelet-v1.15-aws.yaml b/pkg/userdata/centos/testdata/kubelet-v1.15-aws.yaml
index bee716b0..3750c79b 100644
--- a/pkg/userdata/centos/testdata/kubelet-v1.15-aws.yaml
+++ b/pkg/userdata/centos/testdata/kubelet-v1.15-aws.yaml
@@ -371,4 +371,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/centos/testdata/kubelet-v1.16-aws.yaml b/pkg/userdata/centos/testdata/kubelet-v1.16-aws.yaml
index 6e7f9bb5..7072aca7 100644
--- a/pkg/userdata/centos/testdata/kubelet-v1.16-aws.yaml
+++ b/pkg/userdata/centos/testdata/kubelet-v1.16-aws.yaml
@@ -371,4 +371,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/centos/testdata/kubelet-v1.17-aws-external.yaml b/pkg/userdata/centos/testdata/kubelet-v1.17-aws-external.yaml
index 71d56da2..a8496e83 100644
--- a/pkg/userdata/centos/testdata/kubelet-v1.17-aws-external.yaml
+++ b/pkg/userdata/centos/testdata/kubelet-v1.17-aws-external.yaml
@@ -370,4 +370,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/centos/testdata/kubelet-v1.17-aws.yaml b/pkg/userdata/centos/testdata/kubelet-v1.17-aws.yaml
index 76419b94..e6c6c39d 100644
--- a/pkg/userdata/centos/testdata/kubelet-v1.17-aws.yaml
+++ b/pkg/userdata/centos/testdata/kubelet-v1.17-aws.yaml
@@ -371,4 +371,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere-mirrors.yaml b/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere-mirrors.yaml
index ed418f64..f31df455 100644
--- a/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere-mirrors.yaml
+++ b/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere-mirrors.yaml
@@ -392,4 +392,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere-proxy.yaml b/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere-proxy.yaml
index 8d2163b4..821b5bfd 100644
--- a/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere-proxy.yaml
+++ b/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere-proxy.yaml
@@ -392,4 +392,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere.yaml b/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere.yaml
index 84c7e8a3..58cd02b5 100644
--- a/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere.yaml
+++ b/pkg/userdata/centos/testdata/kubelet-v1.17-vsphere.yaml
@@ -379,4 +379,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/flatcar/provider_test.go b/pkg/userdata/flatcar/provider_test.go
index 74f85abb..e4c5d1c7 100644
--- a/pkg/userdata/flatcar/provider_test.go
+++ b/pkg/userdata/flatcar/provider_test.go
@@ -109,6 +109,7 @@ type userDataTestCase struct {
 	registryMirrors       []string
 	pauseImage            string
 	hyperkubeImage        string
+	kubeletImage          string
 }
 
 // TestUserDataGeneration runs the data generation for different
@@ -145,6 +146,39 @@ func TestUserDataGeneration(t *testing.T) {
 			osConfig: &Config{
 				DisableAutoUpdate: true,
 			},
+			hyperkubeImage: "for-kubernetes-less-then-1.18/hyperkubeImage",
+			kubeletImage:   "for-kubernetes-more-then-1.18/kubeletImage",
+		},
+		{
+			name: "v1.18.0",
+			providerSpec: &providerconfigtypes.Config{
+				CloudProvider: "vsphere",
+				SSHPublicKeys: []string{"ssh-rsa AAABBB", "ssh-rsa CCCDDD"},
+				Network: &providerconfigtypes.NetworkConfig{
+					CIDR:    "192.168.81.4/24",
+					Gateway: "192.168.81.1",
+					DNS: providerconfigtypes.DNSConfig{
+						Servers: []string{"8.8.8.8"},
+					},
+				},
+			},
+			spec: clusterv1alpha1.MachineSpec{
+				ObjectMeta: metav1.ObjectMeta{Name: "node1"},
+				Versions: clusterv1alpha1.MachineVersionInfo{
+					Kubelet: "v1.18.0",
+				},
+			},
+			ccProvider: &fakeCloudConfigProvider{
+				name:   "vsphere",
+				config: "{vsphere-config:true}",
+				err:    nil,
+			},
+			DNSIPs: []net.IP{net.ParseIP("10.10.10.10")},
+			osConfig: &Config{
+				DisableAutoUpdate: true,
+			},
+			hyperkubeImage: "for-kubernetes-less-then-1.18/hyperkubeImage",
+			kubeletImage:   "for-kubernetes-more-then-1.18/kubeletImage",
 		},
 	}
 
@@ -188,6 +222,7 @@ func TestUserDataGeneration(t *testing.T) {
 				RegistryMirrors:       test.registryMirrors,
 				PauseImage:            test.pauseImage,
 				HyperkubeImage:        test.hyperkubeImage,
+				KubeletRepository:     test.kubeletImage,
 			}
 
 			s, err := provider.UserData(req)
diff --git a/pkg/userdata/flatcar/testdata/v1.17.0.yaml b/pkg/userdata/flatcar/testdata/v1.17.0.yaml
index 9cbe7215..20722b71 100644
--- a/pkg/userdata/flatcar/testdata/v1.17.0.yaml
+++ b/pkg/userdata/flatcar/testdata/v1.17.0.yaml
@@ -31,7 +31,7 @@ systemd:
     - name: docker.service
       enabled: true
 
-    - name: download-healthcheck-script.service
+    - name: download-script.service
       enabled: true
       contents: |
         [Unit]
@@ -50,8 +50,8 @@ systemd:
       - name: 40-docker.conf
         contents: |
           [Unit]
-          Requires=download-healthcheck-script.service
-          After=download-healthcheck-script.service
+          Requires=download-script.service
+          After=download-script.service
       contents: |
           [Unit]
           Requires=docker.service
@@ -69,8 +69,8 @@ systemd:
       - name: 40-docker.conf
         contents: |
           [Unit]
-          Requires=download-healthcheck-script.service
-          After=download-healthcheck-script.service
+          Requires=download-script.service
+          After=download-script.service
       contents: |
           [Unit]
           Requires=kubelet.service
@@ -111,32 +111,40 @@ systemd:
         MemoryAccounting=true
         EnvironmentFile=-/etc/environment
         EnvironmentFile=/etc/kubernetes/nodeip.conf
-        Environment=KUBELET_IMAGE=docker://k8s.gcr.io/hyperkube-amd64:v1.17.0
-        Environment="RKT_RUN_ARGS=--uuid-file-save=/var/cache/kubelet-pod.uuid \
-          --inherit-env \
-          --insecure-options=image \
-          --volume=resolv,kind=host,source=/etc/resolv.conf \
-          --mount volume=resolv,target=/etc/resolv.conf \
-          --volume cni-bin,kind=host,source=/opt/cni/bin \
-          --mount volume=cni-bin,target=/opt/cni/bin \
-          --volume cni-conf,kind=host,source=/etc/cni/net.d \
-          --mount volume=cni-conf,target=/etc/cni/net.d \
-          --volume etc-kubernetes,kind=host,source=/etc/kubernetes \
-          --mount volume=etc-kubernetes,target=/etc/kubernetes \
-          --volume var-log,kind=host,source=/var/log \
-          --mount volume=var-log,target=/var/log \
-          --volume var-lib-calico,kind=host,source=/var/lib/calico \
-          --mount volume=var-lib-calico,target=/var/lib/calico"
+        Environment=PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/bin
         ExecStartPre=/bin/bash /opt/bin/setup_net_env.sh
         ExecStartPre=/bin/mkdir -p /var/lib/calico
         ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
         ExecStartPre=/bin/mkdir -p /etc/cni/net.d
         ExecStartPre=/bin/mkdir -p /opt/cni/bin
-        ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/cache/kubelet-pod.uuid
-        ExecStartPre=-/bin/rm -rf /var/lib/rkt/cas/tmp/
         ExecStartPre=/bin/bash /opt/load-kernel-modules.sh
-        ExecStart=/usr/lib/flatcar/kubelet-wrapper \
-          kubelet \
+        ExecStartPre=/bin/sh -c '/usr/bin/env > /tmp/environment'
+        ExecStart=/usr/bin/docker run --name %n \
+          --rm --tty --restart no \
+          --network host \
+          --pid host \
+          --env-file /tmp/environment \
+          --privileged \
+          --cgroup-parent system.slice \
+          --entrypoint kubelet \
+          -v /dev:/dev \
+          -v /etc/cni/net.d:/etc/cni/net.d \
+          -v /etc/kubernetes:/etc/kubernetes \
+          -v /etc/machine-id:/etc/machine-id:ro \
+          -v /etc/os-release:/etc/os-release:ro \
+          -v /etc/resolv.conf:/etc/resolv.conf:ro \
+          -v /lib/modules:/lib/modules \
+          -v /mnt:/mnt:rshared \
+          -v /opt/cni/bin:/opt/cni/bin:ro \
+          -v /run:/run \
+          -v /sys:/sys \
+          -v /usr/sbin/iscsiadm:/usr/sbin/iscsiadm \
+          -v /var/lib/calico:/var/lib/calico:ro \
+          -v /var/lib/cni:/var/lib/cni \
+          -v /var/lib/docker:/var/lib/docker \
+          -v /var/lib/kubelet:/var/lib/kubelet:rshared \
+          -v /var/log/pods:/var/log/pods \
+          for-kubernetes-less-then-1.18/hyperkubeImage:v1.17.0 \
           --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \
           --kubeconfig=/var/lib/kubelet/kubeconfig \
           --config=/etc/kubernetes/kubelet.conf \
@@ -152,7 +160,7 @@ systemd:
           --lock-file=/tmp/kubelet.lock \
           --volume-plugin-dir=/var/lib/kubelet/volumeplugins \
           --node-ip ${KUBELET_NODE_IP}
-        ExecStop=-/usr/bin/rkt stop --uuid-file=/var/cache/kubelet-pod.uuid
+        ExecStop=-/usr/bin/docker stop %n
         Restart=always
         RestartSec=10
         [Install]
@@ -452,3 +460,5 @@ storage:
               curl -Lfo /opt/bin/health-monitor.sh https://raw.githubusercontent.com/kubermatic/machine-controller/8b5b66e4910a6228dfaecccaa0a3b05ec4902f8e/pkg/userdata/scripts/health-monitor.sh
               chmod +x /opt/bin/health-monitor.sh
           fi
+
+          systemctl disable download-script.service
diff --git a/pkg/userdata/flatcar/testdata/v1.18.0.yaml b/pkg/userdata/flatcar/testdata/v1.18.0.yaml
new file mode 100644
index 00000000..3ef20d04
--- /dev/null
+++ b/pkg/userdata/flatcar/testdata/v1.18.0.yaml
@@ -0,0 +1,464 @@
+passwd:
+  users:
+    - name: core
+      ssh_authorized_keys:
+        - ssh-rsa AAABBB
+        - ssh-rsa CCCDDD
+
+networkd:
+  units:
+    - name: static-nic.network
+      contents: |
+        [Match]
+        # Because of difficulty predicting specific NIC names on different cloud providers,
+        # we only support static addressing on VSphere. There should be a single NIC attached
+        # that we will match by name prefix 'en' which denotes ethernet devices.
+        Name=en*
+
+        [Network]
+        DHCP=no
+        Address=192.168.81.4/24
+        Gateway=192.168.81.1
+        DNS=8.8.8.8
+
+
+systemd:
+  units:
+    - name: update-engine.service
+      mask: true
+    - name: locksmithd.service
+      mask: true
+    - name: docker.service
+      enabled: true
+
+    - name: download-script.service
+      enabled: true
+      contents: |
+        [Unit]
+        Requires=network-online.target
+        After=network-online.target
+        [Service]
+        Type=oneshot
+        EnvironmentFile=-/etc/environment
+        ExecStart=/opt/bin/download.sh
+        [Install]
+        WantedBy=multi-user.target
+
+    - name: docker-healthcheck.service
+      enabled: true
+      dropins:
+      - name: 40-docker.conf
+        contents: |
+          [Unit]
+          Requires=download-script.service
+          After=download-script.service
+      contents: |
+          [Unit]
+          Requires=docker.service
+          After=docker.service
+
+          [Service]
+          ExecStart=/opt/bin/health-monitor.sh container-runtime
+
+          [Install]
+          WantedBy=multi-user.target
+
+    - name: kubelet-healthcheck.service
+      enabled: true
+      dropins:
+      - name: 40-docker.conf
+        contents: |
+          [Unit]
+          Requires=download-script.service
+          After=download-script.service
+      contents: |
+          [Unit]
+          Requires=kubelet.service
+          After=kubelet.service
+
+          [Service]
+          ExecStart=/opt/bin/health-monitor.sh kubelet
+
+          [Install]
+          WantedBy=multi-user.target
+
+
+    - name: nodeip.service
+      enabled: true
+      contents: |
+        [Unit]
+        Description=Setup Kubelet Node IP Env
+        Requires=network-online.target
+        After=network-online.target
+
+        [Service]
+        ExecStart=/opt/bin/setup_net_env.sh
+        RemainAfterExit=yes
+        Type=oneshot
+        [Install]
+        WantedBy=multi-user.target
+
+    - name: kubelet.service
+      enabled: true
+      contents: |
+        [Unit]
+        Description=Kubernetes Kubelet
+        Requires=docker.service
+        After=docker.service
+        [Service]
+        TimeoutStartSec=5min
+        CPUAccounting=true
+        MemoryAccounting=true
+        EnvironmentFile=-/etc/environment
+        EnvironmentFile=/etc/kubernetes/nodeip.conf
+        Environment=PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/bin
+        ExecStartPre=/bin/bash /opt/bin/setup_net_env.sh
+        ExecStartPre=/bin/mkdir -p /var/lib/calico
+        ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
+        ExecStartPre=/bin/mkdir -p /etc/cni/net.d
+        ExecStartPre=/bin/mkdir -p /opt/cni/bin
+        ExecStartPre=/bin/bash /opt/load-kernel-modules.sh
+        ExecStartPre=/bin/sh -c '/usr/bin/env > /tmp/environment'
+        ExecStart=/usr/bin/docker run --name %n \
+          --rm --tty --restart no \
+          --network host \
+          --pid host \
+          --env-file /tmp/environment \
+          --privileged \
+          --cgroup-parent system.slice \
+          --entrypoint kubelet \
+          -v /dev:/dev \
+          -v /etc/cni/net.d:/etc/cni/net.d \
+          -v /etc/kubernetes:/etc/kubernetes \
+          -v /etc/machine-id:/etc/machine-id:ro \
+          -v /etc/os-release:/etc/os-release:ro \
+          -v /etc/resolv.conf:/etc/resolv.conf:ro \
+          -v /lib/modules:/lib/modules \
+          -v /mnt:/mnt:rshared \
+          -v /opt/cni/bin:/opt/cni/bin:ro \
+          -v /run:/run \
+          -v /sys:/sys \
+          -v /usr/sbin/iscsiadm:/usr/sbin/iscsiadm \
+          -v /var/lib/calico:/var/lib/calico:ro \
+          -v /var/lib/cni:/var/lib/cni \
+          -v /var/lib/docker:/var/lib/docker \
+          -v /var/lib/kubelet:/var/lib/kubelet:rshared \
+          -v /var/log/pods:/var/log/pods \
+          for-kubernetes-more-then-1.18/kubeletImage:v1.18.0 \
+          --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \
+          --kubeconfig=/var/lib/kubelet/kubeconfig \
+          --config=/etc/kubernetes/kubelet.conf \
+          --network-plugin=cni \
+          --cni-conf-dir=/etc/cni/net.d \
+          --cni-bin-dir=/opt/cni/bin \
+          --cert-dir=/etc/kubernetes/pki \
+          --cloud-provider=vsphere \
+          --cloud-config=/etc/kubernetes/cloud-config \
+          --hostname-override=node1 \
+          --dynamic-config-dir=/etc/kubernetes/dynamic-config-dir \
+          --exit-on-lock-contention \
+          --lock-file=/tmp/kubelet.lock \
+          --volume-plugin-dir=/var/lib/kubelet/volumeplugins \
+          --node-ip ${KUBELET_NODE_IP}
+        ExecStop=-/usr/bin/docker stop %n
+        Restart=always
+        RestartSec=10
+        [Install]
+        WantedBy=multi-user.target
+
+    - name: docker.service
+      enabled: true
+      dropins:
+      - name: 10-environment.conf
+        contents: |
+          [Service]
+          EnvironmentFile=-/etc/environment
+
+storage:
+  files:
+
+    - path: "/etc/systemd/journald.conf.d/max_disk_use.conf"
+      filesystem: root
+      mode: 0644
+      contents:
+        inline: |
+          [Journal]
+          SystemMaxUse=5G
+
+
+    - path: "/etc/kubernetes/kubelet.conf"
+      filesystem: root
+      mode: 0644
+      contents:
+        inline: |
+          apiVersion: kubelet.config.k8s.io/v1beta1
+          authentication:
+            anonymous:
+              enabled: false
+            webhook:
+              cacheTTL: 0s
+              enabled: true
+            x509:
+              clientCAFile: /etc/kubernetes/pki/ca.crt
+          authorization:
+            mode: Webhook
+            webhook:
+              cacheAuthorizedTTL: 0s
+              cacheUnauthorizedTTL: 0s
+          cgroupDriver: systemd
+          clusterDNS:
+          - 10.10.10.10
+          clusterDomain: cluster.local
+          cpuManagerReconcilePeriod: 0s
+          evictionPressureTransitionPeriod: 0s
+          featureGates:
+            RotateKubeletServerCertificate: true
+          fileCheckFrequency: 0s
+          httpCheckFrequency: 0s
+          imageMinimumGCAge: 0s
+          kind: KubeletConfiguration
+          kubeReserved:
+            cpu: 100m
+            ephemeral-storage: 1Gi
+            memory: 100Mi
+          nodeStatusReportFrequency: 0s
+          nodeStatusUpdateFrequency: 0s
+          protectKernelDefaults: true
+          rotateCertificates: true
+          runtimeRequestTimeout: 0s
+          serverTLSBootstrap: true
+          staticPodPath: /etc/kubernetes/manifests
+          streamingConnectionIdleTimeout: 0s
+          syncFrequency: 0s
+          systemReserved:
+            cpu: 100m
+            ephemeral-storage: 1Gi
+            memory: 100Mi
+          volumeStatsAggPeriod: 0s
+
+
+    - path: /opt/load-kernel-modules.sh
+      filesystem: root
+      mode: 0755
+      contents:
+        inline: |
+          #!/usr/bin/env bash
+          set -euo pipefail
+
+          modprobe ip_vs
+          modprobe ip_vs_rr
+          modprobe ip_vs_wrr
+          modprobe ip_vs_sh
+
+          if modinfo nf_conntrack_ipv4 &> /dev/null; then
+            modprobe nf_conntrack_ipv4
+          else
+            modprobe nf_conntrack
+          fi
+
+
+    - path: /etc/sysctl.d/k8s.conf
+      filesystem: root
+      mode: 0644
+      contents:
+        inline: |
+          net.bridge.bridge-nf-call-ip6tables = 1
+          net.bridge.bridge-nf-call-iptables = 1
+          kernel.panic_on_oops = 1
+          kernel.panic = 10
+          net.ipv4.ip_forward = 1
+          vm.overcommit_memory = 1
+          fs.inotify.max_user_watches = 1048576
+
+
+    - path: /proc/sys/kernel/panic_on_oops
+      filesystem: root
+      mode: 0644
+      contents:
+        inline: |
+          1
+
+    - path: /proc/sys/kernel/panic
+      filesystem: root
+      mode: 0644
+      contents:
+        inline: |
+          10
+
+    - path: /proc/sys/vm/overcommit_memory
+      filesystem: root
+      mode: 0644
+      contents:
+        inline: |
+          1
+
+    - path: "/opt/bin/setup_net_env.sh"
+      filesystem: root
+      mode: 0755
+      contents:
+        inline: |
+          #!/usr/bin/env bash
+          echodate() {
+            echo "[$(date -Is)]" "$@"
+          }
+
+          # get the default interface IP address
+          DEFAULT_IFC_IP=$(ip -o  route get 1 | grep -oP "src \K\S+")
+
+          if [ -z "${DEFAULT_IFC_IP}" ]
+          then
+          	echodate "Failed to get IP address for the default route interface"
+          	exit 1
+          fi
+
+          # write the nodeip_env file
+          if grep -q coreos /etc/os-release
+          then
+            echo "KUBELET_NODE_IP=${DEFAULT_IFC_IP}" > /etc/kubernetes/nodeip.conf
+          elif [ ! -d /etc/systemd/system/kubelet.service.d ]
+          then
+          	echodate "Can't find kubelet service extras directory"
+          	exit 1
+          else
+            echo -e "[Service]\nEnvironment=\"KUBELET_NODE_IP=${DEFAULT_IFC_IP}\"" > /etc/systemd/system/kubelet.service.d/nodeip.conf
+          fi
+
+
+    - path: /etc/kubernetes/bootstrap-kubelet.conf
+      filesystem: root
+      mode: 0400
+      contents:
+        inline: |
+          apiVersion: v1
+          clusters:
+          - cluster:
+              certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVXakNDQTBLZ0F3SUJBZ0lKQUxmUmxXc0k4WVFITUEwR0NTcUdTSWIzRFFFQkJRVUFNSHN4Q3pBSkJnTlYKQkFZVEFsVlRNUXN3Q1FZRFZRUUlFd0pEUVRFV01CUUdBMVVFQnhNTlUyRnVJRVp5WVc1amFYTmpiekVVTUJJRwpBMVVFQ2hNTFFuSmhaR1pwZEhwcGJtTXhFakFRQmdOVkJBTVRDV3h2WTJGc2FHOXpkREVkTUJzR0NTcUdTSWIzCkRRRUpBUllPWW5KaFpFQmtZVzVuWVM1amIyMHdIaGNOTVRRd056RTFNakEwTmpBMVdoY05NVGN3TlRBME1qQTAKTmpBMVdqQjdNUXN3Q1FZRFZRUUdFd0pWVXpFTE1Ba0dBMVVFQ0JNQ1EwRXhGakFVQmdOVkJBY1REVk5oYmlCRwpjbUZ1WTJselkyOHhGREFTQmdOVkJBb1RDMEp5WVdSbWFYUjZhVzVqTVJJd0VBWURWUVFERXdsc2IyTmhiR2h2CmMzUXhIVEFiQmdrcWhraUc5dzBCQ1FFV0RtSnlZV1JBWkdGdVoyRXVZMjl0TUlJQklqQU5CZ2txaGtpRzl3MEIKQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdDVmQWpwNGZUY2VrV1VUZnpzcDBreWloMU9ZYnNHTDBLWDFlUmJTUwpSOE9kMCs5UTYySHlueStHRndNVGI0QS9LVThtc3NvSHZjY2VTQUFid2ZieEZLLytzNTFUb2JxVW5PUlpyT29UClpqa1V5Z2J5WERTSzk5WUJiY1IxUGlwOHZ3TVRtNFhLdUx0Q2lnZUJCZGpqQVFkZ1VPMjhMRU5HbHNNbm1lWWsKSmZPRFZHblZtcjVMdGI5QU5BOElLeVRmc25ISjRpT0NTL1BsUGJVajJxN1lub1ZMcG9zVUJNbGdVYi9DeWtYMwptT29MYjR5SkpReUEvaVNUNlp4aUlFajM2RDR5V1o1bGc3WUpsK1VpaUJRSEdDblBkR3lpcHFWMDZleDBoZVlXCmNhaVc4TFdaU1VROTNqUStXVkNIOGhUN0RRTzFkbXN2VW1YbHEvSmVBbHdRL1FJREFRQUJvNEhnTUlIZE1CMEcKQTFVZERnUVdCQlJjQVJPdGhTNFA0VTd2VGZqQnlDNTY5UjdFNkRDQnJRWURWUjBqQklHbE1JR2lnQlJjQVJPdApoUzRQNFU3dlRmakJ5QzU2OVI3RTZLRi9wSDB3ZXpFTE1Ba0dBMVVFQmhNQ1ZWTXhDekFKQmdOVkJBZ1RBa05CCk1SWXdGQVlEVlFRSEV3MVRZVzRnUm5KaGJtTnBjMk52TVJRd0VnWURWUVFLRXd0Q2NtRmtabWwwZW1sdVl6RVMKTUJBR0ExVUVBeE1KYkc5allXeG9iM04wTVIwd0d3WUpLb1pJaHZjTkFRa0JGZzVpY21Ga1FHUmhibWRoTG1OdgpiWUlKQUxmUmxXc0k4WVFITUF3R0ExVWRFd1FGTUFNQkFmOHdEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRzZoClU5ZjlzTkgwLzZvQmJHR3kyRVZVMFVnSVRVUUlyRldvOXJGa3JXNWsvWGtEalFtKzNsempUMGlHUjRJeEUvQW8KZVU2c1FodWE3d3JXZUZFbjQ3R0w5OGxuQ3NKZEQ3b1pOaEZtUTk1VGIvTG5EVWpzNVlqOWJyUDBOV3pYZllVNApVSzJabklOSlJjSnBCOGlSQ2FDeEU4RGRjVUYwWHFJRXE2cEEyNzJzbm9MbWlYTE12Tmwza1lFZG0ramU2dm9ECjU4U05WRVVzenR6UXlYbUpFaENwd1ZJMEE2UUNqelhqK3F2cG13M1paSGk4SndYZWk4WlpCTFRTRkJraThaN24Kc0g5QkJIMzgvU3pVbUFONFFIU1B5MWdqcW0wME9BRThOYVlEa2gvYnpFNGQ3bUxHR01XcC9XRTNLUFN1ODJIRgprUGU2WG9TYmlMbS9reGszMlQwPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t
+              server: https://server:443
+            name: ""
+          contexts: []
+          current-context: ""
+          kind: Config
+          preferences: {}
+          users:
+          - name: ""
+            user:
+              token: my-token
+
+
+    - path: /etc/kubernetes/cloud-config
+      filesystem: root
+      mode: 0400
+      contents:
+        inline: |
+          {vsphere-config:true}
+
+    - path: /etc/kubernetes/pki/ca.crt
+      filesystem: root
+      mode: 0644
+      contents:
+        inline: |
+          -----BEGIN CERTIFICATE-----
+          MIIEWjCCA0KgAwIBAgIJALfRlWsI8YQHMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNV
+          BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEUMBIG
+          A1UEChMLQnJhZGZpdHppbmMxEjAQBgNVBAMTCWxvY2FsaG9zdDEdMBsGCSqGSIb3
+          DQEJARYOYnJhZEBkYW5nYS5jb20wHhcNMTQwNzE1MjA0NjA1WhcNMTcwNTA0MjA0
+          NjA1WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBG
+          cmFuY2lzY28xFDASBgNVBAoTC0JyYWRmaXR6aW5jMRIwEAYDVQQDEwlsb2NhbGhv
+          c3QxHTAbBgkqhkiG9w0BCQEWDmJyYWRAZGFuZ2EuY29tMIIBIjANBgkqhkiG9w0B
+          AQEFAAOCAQ8AMIIBCgKCAQEAt5fAjp4fTcekWUTfzsp0kyih1OYbsGL0KX1eRbSS
+          R8Od0+9Q62Hyny+GFwMTb4A/KU8mssoHvcceSAAbwfbxFK/+s51TobqUnORZrOoT
+          ZjkUygbyXDSK99YBbcR1Pip8vwMTm4XKuLtCigeBBdjjAQdgUO28LENGlsMnmeYk
+          JfODVGnVmr5Ltb9ANA8IKyTfsnHJ4iOCS/PlPbUj2q7YnoVLposUBMlgUb/CykX3
+          mOoLb4yJJQyA/iST6ZxiIEj36D4yWZ5lg7YJl+UiiBQHGCnPdGyipqV06ex0heYW
+          caiW8LWZSUQ93jQ+WVCH8hT7DQO1dmsvUmXlq/JeAlwQ/QIDAQABo4HgMIHdMB0G
+          A1UdDgQWBBRcAROthS4P4U7vTfjByC569R7E6DCBrQYDVR0jBIGlMIGigBRcAROt
+          hS4P4U7vTfjByC569R7E6KF/pH0wezELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB
+          MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQKEwtCcmFkZml0emluYzES
+          MBAGA1UEAxMJbG9jYWxob3N0MR0wGwYJKoZIhvcNAQkBFg5icmFkQGRhbmdhLmNv
+          bYIJALfRlWsI8YQHMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAG6h
+          U9f9sNH0/6oBbGGy2EVU0UgITUQIrFWo9rFkrW5k/XkDjQm+3lzjT0iGR4IxE/Ao
+          eU6sQhua7wrWeFEn47GL98lnCsJdD7oZNhFmQ95Tb/LnDUjs5Yj9brP0NWzXfYU4
+          UK2ZnINJRcJpB8iRCaCxE8DdcUF0XqIEq6pA272snoLmiXLMvNl3kYEdm+je6voD
+          58SNVEUsztzQyXmJEhCpwVI0A6QCjzXj+qvpmw3ZZHi8JwXei8ZZBLTSFBki8Z7n
+          sH9BBH38/SzUmAN4QHSPy1gjqm00OAE8NaYDkh/bzE4d7mLGGMWp/WE3KPSu82HF
+          kPe6XoSbiLm/kxk32T0=
+          -----END CERTIFICATE-----
+
+    - path: /etc/hostname
+      filesystem: root
+      mode: 0600
+      contents:
+        inline: 'node1'
+
+    - path: /etc/ssh/sshd_config
+      filesystem: root
+      mode: 0600
+      user:
+        id: 0
+      group:
+        id: 0
+      contents:
+        inline: |
+          # Use most defaults for sshd configuration.
+          Subsystem sftp internal-sftp
+          ClientAliveInterval 180
+          UseDNS no
+          UsePAM yes
+          PrintLastLog no # handled by PAM
+          PrintMotd no # handled by PAM
+          PasswordAuthentication no
+          ChallengeResponseAuthentication no
+
+    - path: /etc/docker/daemon.json
+      filesystem: root
+      mode: 0644
+      contents:
+        inline: |
+          {"exec-opts":["native.cgroupdriver=systemd"],"storage-driver":"overlay2","log-driver":"json-file","log-opts":{"max-size":"100m"}}
+
+    - path: /opt/bin/download.sh
+      filesystem: root
+      mode: 0755
+      contents:
+        inline: |
+          #!/bin/bash
+          set -xeuo pipefail
+          opt_bin=/opt/bin
+          cni_bin_dir=/opt/cni/bin
+          mkdir -p /etc/cni/net.d /etc/kubernetes/dynamic-config-dir /etc/kubernetes/manifests "$opt_bin" "$cni_bin_dir"
+          arch=${HOST_ARCH:-amd64}
+          CNI_VERSION="${CNI_VERSION:-v0.8.6}"
+          cni_base_url="https://github.com/containernetworking/plugins/releases/download/$CNI_VERSION"
+          cni_filename="cni-plugins-linux-$arch-$CNI_VERSION.tgz"
+          curl -Lfo "$cni_bin_dir/$cni_filename" "$cni_base_url/$cni_filename"
+          cni_sum=$(curl -Lf "$cni_base_url/$cni_filename.sha256")
+          cd "$cni_bin_dir"
+          sha256sum -c <<<"$cni_sum"
+          tar xvf "$cni_filename"
+          rm -f "$cni_filename"
+          cd -
+          KUBE_VERSION="${KUBE_VERSION:-v1.18.0}"
+          kube_dir="$opt_bin/kubernetes-$KUBE_VERSION"
+          kube_base_url="https://storage.googleapis.com/kubernetes-release/release/$KUBE_VERSION/bin/linux/$arch"
+          kube_sum_file="$kube_dir/sha256"
+          mkdir -p "$kube_dir"
+          : >"$kube_sum_file"
+
+          for bin in kubelet kubeadm kubectl; do
+              curl -Lfo "$kube_dir/$bin" "$kube_base_url/$bin"
+              chmod +x "$kube_dir/$bin"
+              sum=$(curl -Lf "$kube_base_url/$bin.sha256")
+              echo "$sum  $kube_dir/$bin" >>"$kube_sum_file"
+          done
+          sha256sum -c "$kube_sum_file"
+
+          for bin in kubelet kubeadm kubectl; do
+              ln -sf "$kube_dir/$bin" "$opt_bin"/$bin
+          done
+
+          if [[ ! -x /opt/bin/health-monitor.sh ]]; then
+              curl -Lfo /opt/bin/health-monitor.sh https://raw.githubusercontent.com/kubermatic/machine-controller/8b5b66e4910a6228dfaecccaa0a3b05ec4902f8e/pkg/userdata/scripts/health-monitor.sh
+              chmod +x /opt/bin/health-monitor.sh
+          fi
+
+          systemctl disable download-script.service
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.15-aws.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.15-aws.yaml
index 6d4317bb..9e411fb6 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.15-aws.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.15-aws.yaml
@@ -376,4 +376,4 @@ rh_subscription:
     auto-attach: true
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.16-aws.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.16-aws.yaml
index 778e1d21..9b878d62 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.16-aws.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.16-aws.yaml
@@ -376,4 +376,4 @@ rh_subscription:
     auto-attach: true
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.17-aws-external.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.17-aws-external.yaml
index 5f91d3ce..3a086ba6 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.17-aws-external.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.17-aws-external.yaml
@@ -375,4 +375,4 @@ rh_subscription:
     auto-attach: true
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.17-aws.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.17-aws.yaml
index eb0bc89c..4b93170e 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.17-aws.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.17-aws.yaml
@@ -376,4 +376,4 @@ rh_subscription:
     auto-attach: true
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere-mirrors.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere-mirrors.yaml
index 08acd4e9..dea5f4a1 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere-mirrors.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere-mirrors.yaml
@@ -397,4 +397,4 @@ rh_subscription:
     auto-attach: true
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere-proxy.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere-proxy.yaml
index ecfc3d20..ac076fe5 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere-proxy.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere-proxy.yaml
@@ -397,4 +397,4 @@ rh_subscription:
     auto-attach: true
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere.yaml b/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere.yaml
index c92e948f..98dcbdff 100644
--- a/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere.yaml
+++ b/pkg/userdata/rhel/testdata/kubelet-v1.17-vsphere.yaml
@@ -384,4 +384,4 @@ rh_subscription:
     auto-attach: true
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/dist-upgrade-on-boot.yaml b/pkg/userdata/sles/testdata/dist-upgrade-on-boot.yaml
index 6cf2157d..551312fd 100644
--- a/pkg/userdata/sles/testdata/dist-upgrade-on-boot.yaml
+++ b/pkg/userdata/sles/testdata/dist-upgrade-on-boot.yaml
@@ -356,4 +356,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/kubelet-version-without-v-prefix.yaml b/pkg/userdata/sles/testdata/kubelet-version-without-v-prefix.yaml
index c4434137..e4d7de84 100644
--- a/pkg/userdata/sles/testdata/kubelet-version-without-v-prefix.yaml
+++ b/pkg/userdata/sles/testdata/kubelet-version-without-v-prefix.yaml
@@ -354,4 +354,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/multiple-dns-servers.yaml b/pkg/userdata/sles/testdata/multiple-dns-servers.yaml
index 5d603f69..79ea98c2 100644
--- a/pkg/userdata/sles/testdata/multiple-dns-servers.yaml
+++ b/pkg/userdata/sles/testdata/multiple-dns-servers.yaml
@@ -356,4 +356,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/multiple-ssh-keys.yaml b/pkg/userdata/sles/testdata/multiple-ssh-keys.yaml
index be5145f4..ac88eff8 100644
--- a/pkg/userdata/sles/testdata/multiple-ssh-keys.yaml
+++ b/pkg/userdata/sles/testdata/multiple-ssh-keys.yaml
@@ -356,4 +356,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/openstack-overwrite-cloud-config.yaml b/pkg/userdata/sles/testdata/openstack-overwrite-cloud-config.yaml
index c03702bc..dcb07e50 100644
--- a/pkg/userdata/sles/testdata/openstack-overwrite-cloud-config.yaml
+++ b/pkg/userdata/sles/testdata/openstack-overwrite-cloud-config.yaml
@@ -358,4 +358,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/openstack.yaml b/pkg/userdata/sles/testdata/openstack.yaml
index 0b9fba96..ce87e325 100644
--- a/pkg/userdata/sles/testdata/openstack.yaml
+++ b/pkg/userdata/sles/testdata/openstack.yaml
@@ -358,4 +358,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/version-1.15.10.yaml b/pkg/userdata/sles/testdata/version-1.15.10.yaml
index bf101607..b827f08b 100644
--- a/pkg/userdata/sles/testdata/version-1.15.10.yaml
+++ b/pkg/userdata/sles/testdata/version-1.15.10.yaml
@@ -354,4 +354,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/version-1.16.3.yaml b/pkg/userdata/sles/testdata/version-1.16.3.yaml
index 0d852e90..5952710c 100644
--- a/pkg/userdata/sles/testdata/version-1.16.3.yaml
+++ b/pkg/userdata/sles/testdata/version-1.16.3.yaml
@@ -354,4 +354,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/version-1.17.1.yaml b/pkg/userdata/sles/testdata/version-1.17.1.yaml
index 500911cb..541c37fa 100644
--- a/pkg/userdata/sles/testdata/version-1.17.1.yaml
+++ b/pkg/userdata/sles/testdata/version-1.17.1.yaml
@@ -354,4 +354,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/vsphere-mirrors.yaml b/pkg/userdata/sles/testdata/vsphere-mirrors.yaml
index b40feb48..61b6c195 100644
--- a/pkg/userdata/sles/testdata/vsphere-mirrors.yaml
+++ b/pkg/userdata/sles/testdata/vsphere-mirrors.yaml
@@ -369,4 +369,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/vsphere-proxy.yaml b/pkg/userdata/sles/testdata/vsphere-proxy.yaml
index 4900f929..12498843 100644
--- a/pkg/userdata/sles/testdata/vsphere-proxy.yaml
+++ b/pkg/userdata/sles/testdata/vsphere-proxy.yaml
@@ -369,4 +369,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/sles/testdata/vsphere.yaml b/pkg/userdata/sles/testdata/vsphere.yaml
index 145d1ac1..fa27d1c2 100644
--- a/pkg/userdata/sles/testdata/vsphere.yaml
+++ b/pkg/userdata/sles/testdata/vsphere.yaml
@@ -359,4 +359,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/dist-upgrade-on-boot.yaml b/pkg/userdata/ubuntu/testdata/dist-upgrade-on-boot.yaml
index 154989ae..948545d5 100644
--- a/pkg/userdata/ubuntu/testdata/dist-upgrade-on-boot.yaml
+++ b/pkg/userdata/ubuntu/testdata/dist-upgrade-on-boot.yaml
@@ -456,4 +456,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/kubelet-version-without-v-prefix.yaml b/pkg/userdata/ubuntu/testdata/kubelet-version-without-v-prefix.yaml
index e95372d3..de1d643d 100644
--- a/pkg/userdata/ubuntu/testdata/kubelet-version-without-v-prefix.yaml
+++ b/pkg/userdata/ubuntu/testdata/kubelet-version-without-v-prefix.yaml
@@ -454,4 +454,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/multiple-dns-servers.yaml b/pkg/userdata/ubuntu/testdata/multiple-dns-servers.yaml
index 5c4e3115..780063a4 100644
--- a/pkg/userdata/ubuntu/testdata/multiple-dns-servers.yaml
+++ b/pkg/userdata/ubuntu/testdata/multiple-dns-servers.yaml
@@ -456,4 +456,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/multiple-ssh-keys.yaml b/pkg/userdata/ubuntu/testdata/multiple-ssh-keys.yaml
index 10e9f5e7..5043efe3 100644
--- a/pkg/userdata/ubuntu/testdata/multiple-ssh-keys.yaml
+++ b/pkg/userdata/ubuntu/testdata/multiple-ssh-keys.yaml
@@ -456,4 +456,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/openstack-overwrite-cloud-config.yaml b/pkg/userdata/ubuntu/testdata/openstack-overwrite-cloud-config.yaml
index 4f13ad72..750effa4 100644
--- a/pkg/userdata/ubuntu/testdata/openstack-overwrite-cloud-config.yaml
+++ b/pkg/userdata/ubuntu/testdata/openstack-overwrite-cloud-config.yaml
@@ -458,4 +458,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/openstack.yaml b/pkg/userdata/ubuntu/testdata/openstack.yaml
index 7f3391b8..646cf08a 100644
--- a/pkg/userdata/ubuntu/testdata/openstack.yaml
+++ b/pkg/userdata/ubuntu/testdata/openstack.yaml
@@ -458,4 +458,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/version-1.15.10.yaml b/pkg/userdata/ubuntu/testdata/version-1.15.10.yaml
index a758b840..51c2a890 100644
--- a/pkg/userdata/ubuntu/testdata/version-1.15.10.yaml
+++ b/pkg/userdata/ubuntu/testdata/version-1.15.10.yaml
@@ -454,4 +454,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/version-1.16.6.yaml b/pkg/userdata/ubuntu/testdata/version-1.16.6.yaml
index 5588981b..7cca6f3a 100644
--- a/pkg/userdata/ubuntu/testdata/version-1.16.6.yaml
+++ b/pkg/userdata/ubuntu/testdata/version-1.16.6.yaml
@@ -454,4 +454,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/version-1.17.3.yaml b/pkg/userdata/ubuntu/testdata/version-1.17.3.yaml
index e95372d3..de1d643d 100644
--- a/pkg/userdata/ubuntu/testdata/version-1.17.3.yaml
+++ b/pkg/userdata/ubuntu/testdata/version-1.17.3.yaml
@@ -454,4 +454,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/vsphere-mirrors.yaml b/pkg/userdata/ubuntu/testdata/vsphere-mirrors.yaml
index d0101da6..8ea19770 100644
--- a/pkg/userdata/ubuntu/testdata/vsphere-mirrors.yaml
+++ b/pkg/userdata/ubuntu/testdata/vsphere-mirrors.yaml
@@ -469,4 +469,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/vsphere-proxy.yaml b/pkg/userdata/ubuntu/testdata/vsphere-proxy.yaml
index 2c4e9e76..300166cb 100644
--- a/pkg/userdata/ubuntu/testdata/vsphere-proxy.yaml
+++ b/pkg/userdata/ubuntu/testdata/vsphere-proxy.yaml
@@ -469,4 +469,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/pkg/userdata/ubuntu/testdata/vsphere.yaml b/pkg/userdata/ubuntu/testdata/vsphere.yaml
index 812fd47a..f81f96c1 100644
--- a/pkg/userdata/ubuntu/testdata/vsphere.yaml
+++ b/pkg/userdata/ubuntu/testdata/vsphere.yaml
@@ -459,4 +459,4 @@ write_files:
     EnvironmentFile=-/etc/environment
 
 runcmd:
-- systemctl enable --now setup.service
+- systemctl start setup.service
diff --git a/test/e2e/provisioning/all_e2e_test.go b/test/e2e/provisioning/all_e2e_test.go
index d4034be9..2f1596d4 100644
--- a/test/e2e/provisioning/all_e2e_test.go
+++ b/test/e2e/provisioning/all_e2e_test.go
@@ -371,7 +371,7 @@ func TestPacketProvisioningE2E(t *testing.T) {
 		t.Fatal("unable to run the test suite, PACKET_PROJECT_ID environment variable cannot be empty")
 	}
 
-	selector := Not(OsSelector("sles", "rhel", "flatcar"))
+	selector := Not(OsSelector("sles", "rhel"))
 
 	// act
 	params := []string{
diff --git a/test/e2e/provisioning/testdata/machinedeployment-packet.yaml b/test/e2e/provisioning/testdata/machinedeployment-packet.yaml
index 917bf4c5..d487b98f 100644
--- a/test/e2e/provisioning/testdata/machinedeployment-packet.yaml
+++ b/test/e2e/provisioning/testdata/machinedeployment-packet.yaml
@@ -26,9 +26,9 @@ spec:
           cloudProviderSpec:
             apiKey: << PACKET_API_KEY >>
             projectID: << PACKET_PROJECT_ID >>
-            instanceType: "t1.small.x86"
+            instanceType: "c1.small.x86"
             facilities:
-            - "ewr1"
+            - "ams1"
           operatingSystem: "<< OS_NAME >>"
           operatingSystemSpec:
             distUpgradeOnBoot: false