mirror of
https://github.com/puppetmaster/typhoon.git
synced 2025-08-04 16:31:34 +02:00
Compare commits
140 Commits
Author | SHA1 | Date | |
---|---|---|---|
201a38bd90 | |||
fbdd946601 | |||
19102636a9 | |||
21e540159b | |||
43e65a4d13 | |||
e79088baa0 | |||
495e33e213 | |||
63f5a26a72 | |||
eea79e895d | |||
99c07661c6 | |||
521a1f0fee | |||
7345cb6419 | |||
a481d71d7d | |||
831a5c976c | |||
85e6783503 | |||
165396d6aa | |||
ce49a93d5d | |||
e623439eec | |||
9548572d98 | |||
f00ecde854 | |||
d85300f947 | |||
65f006e6cc | |||
8d3817e0ae | |||
5f5eec1175 | |||
5308fde3d3 | |||
9ab61d7bf5 | |||
6483f613c5 | |||
56c6bf431a | |||
63ab117205 | |||
1cd262e712 | |||
32bdda1b6c | |||
07d257aa7b | |||
fd96067125 | |||
9d16f5c78a | |||
159443bae7 | |||
119dc859d3 | |||
5f6b0728c5 | |||
d774c51297 | |||
f6a8fb363e | |||
f570af9418 | |||
4ec6732b98 | |||
ea1efb536a | |||
451fd86470 | |||
b1b611b22c | |||
eabf00fbf1 | |||
8eaa72c1ca | |||
58cf82da56 | |||
ccc832f468 | |||
90f8d62204 | |||
af5c413abf | |||
168c487484 | |||
805dd772a8 | |||
c6ec6596d8 | |||
47a9989927 | |||
10b977d54a | |||
b7a268fc45 | |||
279f36effd | |||
77fc14db71 | |||
2b0296d671 | |||
7b38271212 | |||
ae07a21e3d | |||
0ab1ae3210 | |||
67e3d2b86e | |||
a48dd9ebd8 | |||
26a291aef4 | |||
251a14519f | |||
6300383b43 | |||
e32885c9cd | |||
fe8afdbee9 | |||
878f5a3647 | |||
34ec7e9862 | |||
f6c6e85f84 | |||
8582e19077 | |||
3727c40c6c | |||
b608f9c615 | |||
ec1dbb853c | |||
d046d45769 | |||
a73f57fe4e | |||
60bc8957c9 | |||
8b78c65483 | |||
f86c00288f | |||
a57b3cf973 | |||
10c5487ad7 | |||
e4c479554c | |||
be113e77b4 | |||
911c53e4ae | |||
bfa8dfc75d | |||
43dc44623f | |||
734bc1d32a | |||
41e632280f | |||
fc22f04dd6 | |||
377e14c80b | |||
9ec8ec4afc | |||
5c1ed37ff5 | |||
e765fb310d | |||
7b5ffd0085 | |||
123439c2a4 | |||
11453bac91 | |||
dd0c61d1d9 | |||
5c87529011 | |||
a97df839ea | |||
a5290dac32 | |||
308c7dfb6e | |||
da63c89d71 | |||
62d7ccfff3 | |||
1bc25c1036 | |||
2d5a4ae1ef | |||
1ab27ae1f1 | |||
def84aa5a0 | |||
dd883988bd | |||
e0d8917573 | |||
f7f983c7da | |||
b20233e05d | |||
77e387cf83 | |||
795428329a | |||
f7dd959e9c | |||
b62a6def23 | |||
1b5caef4c1 | |||
767efabeb2 | |||
68726a2773 | |||
4ea85b1ac8 | |||
74d8b9dabe | |||
777c860b1c | |||
b033a94efc | |||
235c8a5222 | |||
69cabd9486 | |||
bca96bb124 | |||
cd368c123f | |||
7c733bd314 | |||
229a4c5293 | |||
47387d552a | |||
7c046b6206 | |||
d8e4ac172a | |||
663f37ed6d | |||
fb5f63c8be | |||
0d6410505d | |||
2a2ed372c8 | |||
2ff6d602d8 | |||
64e8d207b1 | |||
a441f5c6e0 |
159
CHANGES.md
Normal file
159
CHANGES.md
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
# Typhoon
|
||||||
|
|
||||||
|
Notable changes between versions.
|
||||||
|
|
||||||
|
## Latest
|
||||||
|
|
||||||
|
## v1.8.6
|
||||||
|
|
||||||
|
* Kubernetes [v1.8.6](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.8.md#v186)
|
||||||
|
|
||||||
|
## v1.8.5
|
||||||
|
|
||||||
|
* Kubernetes [v1.8.5](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.8.md#v185)
|
||||||
|
* Recommend Container Linux [images](https://coreos.com/releases/) with Docker 17.09
|
||||||
|
* Container Linux stable, beta, and alpha now provide Docker 17.09 (instead
|
||||||
|
of 1.12)
|
||||||
|
* Older clusters (with CLUO addon) auto-update Container Linux version to begin using Docker 17.09
|
||||||
|
* Fix race where `etcd-member.service` could fail to resolve peers ([#69](https://github.com/poseidon/typhoon/pull/69))
|
||||||
|
* Add optional `cluster_domain_suffix` variable (#74)
|
||||||
|
* Use kubernetes-incubator/bootkube v0.9.1
|
||||||
|
|
||||||
|
#### Bare-Metal
|
||||||
|
|
||||||
|
* Add kubelet `--volume-plugin-dir` flag to allow flexvolume providers ([#61](https://github.com/poseidon/typhoon/pull/61))
|
||||||
|
|
||||||
|
#### Addons
|
||||||
|
|
||||||
|
* Discourage deploying the Kubernetes Dashboard (security)
|
||||||
|
|
||||||
|
## v1.8.4
|
||||||
|
|
||||||
|
* Kubernetes v1.8.4
|
||||||
|
* Calico related bug fixes
|
||||||
|
* Update Calico from v2.6.1 to v2.6.3
|
||||||
|
* Update flannel from v0.9.0 to v0.9.1
|
||||||
|
* Service accounts for kube-proxy and pod-checkpointer
|
||||||
|
* Use kubernetes-incubator/bootkube v0.9.0
|
||||||
|
|
||||||
|
## v1.8.3
|
||||||
|
|
||||||
|
* Kubernetes v1.8.3
|
||||||
|
* Run etcd on-host, across controllers
|
||||||
|
* Promote AWS platform to beta
|
||||||
|
* Use kubernetes-incubator/bootkube v0.8.2
|
||||||
|
|
||||||
|
#### Google Cloud
|
||||||
|
|
||||||
|
* Add required variable `region` (e.g. "us-central1")
|
||||||
|
* Reduce time to bootstrap a cluster
|
||||||
|
* Change etcd to run on-host, across controllers (etcd-member.service)
|
||||||
|
* Change controller instances to automatically span zones in the region
|
||||||
|
* Change worker managed instance group to automatically span zones in the region
|
||||||
|
* Improve internal firewall rules and use tag-based firewall policies
|
||||||
|
* Remove support for self-hosted etcd
|
||||||
|
* Remove the `zone` required variable
|
||||||
|
* Remove the `controller_preemptible` optional variable
|
||||||
|
|
||||||
|
#### AWS
|
||||||
|
|
||||||
|
* Promote AWS platform to beta
|
||||||
|
* Reduce time to bootstrap a cluster
|
||||||
|
* Change etcd to run on-host, across controllers (etcd-member.service)
|
||||||
|
* Fix firewall rules for multi-controller kubelet scraping and node-exporter
|
||||||
|
* Remove support for self-hosted etcd
|
||||||
|
|
||||||
|
#### Addons
|
||||||
|
|
||||||
|
* Add Prometheus 2.0 addon with alerting rules
|
||||||
|
* Add Grafana dashboard for observing metrics
|
||||||
|
|
||||||
|
## v1.8.2
|
||||||
|
|
||||||
|
* Kubernetes v1.8.2
|
||||||
|
* Fixes a memory leak in the v1.8.1 apiserver ([kubernetes#53485](https://github.com/kubernetes/kubernetes/issues/53485))
|
||||||
|
* Switch to using the `gcr.io/google_containers/hyperkube`
|
||||||
|
* Update flannel from v0.8.0 to v0.9.0
|
||||||
|
* Add `hairpinMode` to flannel CNI config
|
||||||
|
* Add `--no-negcache` to kube-dns dnsmasq
|
||||||
|
* Use kubernetes-incubator/bootkube v0.8.1
|
||||||
|
|
||||||
|
## v1.8.1
|
||||||
|
|
||||||
|
* Kubernetes v1.8.1
|
||||||
|
* Use kubernetes-incubator/bootkube v0.8.0
|
||||||
|
|
||||||
|
#### Digital Ocean
|
||||||
|
|
||||||
|
* Run etcd cluster across controller nodes (etcd-member.service)
|
||||||
|
* Remove support for self-hosted etcd
|
||||||
|
* Reduce time to bootstrap a cluster
|
||||||
|
|
||||||
|
## v1.7.7
|
||||||
|
|
||||||
|
* Kubernetes v1.7.7
|
||||||
|
* Use kubernetes-incubator/bootkube v0.7.0
|
||||||
|
* Update kube-dns to 1.14.5 to fix dnsmasq [vulnerability](https://security.googleblog.com/2017/10/behind-masq-yet-more-dns-and-dhcp.html)
|
||||||
|
* Calico v2.6.1
|
||||||
|
* flannel-cni v0.3.0
|
||||||
|
* Update flannel CNI config to fix hostPort
|
||||||
|
|
||||||
|
## v1.7.5
|
||||||
|
|
||||||
|
* Kubernetes v1.7.5
|
||||||
|
* Use kubernetes-incubator/bootkube v0.6.2
|
||||||
|
* Add AWS Terraform module (alpha)
|
||||||
|
* Add support for Calico networking (bare-metal, Google Cloud, AWS)
|
||||||
|
* Change networking default from "flannel" to "calico"
|
||||||
|
|
||||||
|
#### AWS
|
||||||
|
|
||||||
|
* Add `network_mtu` to allow CNI interface MTU customization
|
||||||
|
|
||||||
|
#### Bare-Metal
|
||||||
|
|
||||||
|
* Add `network_mtu` to allow CNI interface MTU customization
|
||||||
|
* Remove support for `experimental_self_hosted_etcd`
|
||||||
|
|
||||||
|
## v1.7.3
|
||||||
|
|
||||||
|
* Kubernetes v1.7.3
|
||||||
|
* Use kubernetes-incubator/bootkube v0.6.1
|
||||||
|
|
||||||
|
#### Digital Ocean
|
||||||
|
|
||||||
|
* Add cloud firewall rules (requires Terraform v0.10)
|
||||||
|
* Change nodes tags from strings to DO tags
|
||||||
|
|
||||||
|
## v1.7.1
|
||||||
|
|
||||||
|
* Kubernetes v1.7.1
|
||||||
|
* Use kubernetes-incubator/bootkube v0.6.0
|
||||||
|
* Add Bare-Metal Terraform module (stable)
|
||||||
|
* Add Digital Ocean Terraform module (beta)
|
||||||
|
|
||||||
|
#### Google Cloud
|
||||||
|
|
||||||
|
* Remove `k8s_domain_name` variable, `cluster_name` + `dns_zone` resolves to controllers
|
||||||
|
* Rename `dns_base_zone` to `dns_zone`
|
||||||
|
* Rename `dns_base_zone_name` to `dns_zone_name`
|
||||||
|
|
||||||
|
## v1.6.7
|
||||||
|
|
||||||
|
* Kubernetes v1.6.7
|
||||||
|
* Use kubernetes-incubator/bootkube v0.5.1
|
||||||
|
|
||||||
|
## v1.6.6
|
||||||
|
|
||||||
|
* Kubernetes v1.6.6
|
||||||
|
* Use kubernetes-incubator/bootkube v0.4.5
|
||||||
|
* Disable locksmithd on hosts, in favor of [CLUO](https://github.com/coreos/container-linux-update-operator).
|
||||||
|
|
||||||
|
## v1.6.4
|
||||||
|
|
||||||
|
* Kubernetes v1.6.4
|
||||||
|
* Add Google Cloud Terraform module (stable)
|
||||||
|
|
||||||
|
## Earlier
|
||||||
|
|
||||||
|
Earlier versions, back to v1.3.0, used different designs and mechanisms.
|
@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
## Developer Certificate of Origin
|
## Developer Certificate of Origin
|
||||||
|
|
||||||
By contributing, you agree to the Linux Foundation's Developer Certificate of Origin ([DOC](DCO)). The DCO is a statement that you, the contributor, have the legal right to make your contribution and understand the contribution will be distributed as part of this project.
|
By contributing, you agree to the Linux Foundation's Developer Certificate of Origin ([DCO](DCO)). The DCO is a statement that you, the contributor, have the legal right to make your contribution and understand the contribution will be distributed as part of this project.
|
||||||
|
57
README.md
57
README.md
@ -1,4 +1,4 @@
|
|||||||
# Typhoon <img align="right" src="https://storage.googleapis.com/dghubble/spin.png">
|
# Typhoon []() <img align="right" src="https://storage.googleapis.com/poseidon/typhoon-logo.png">
|
||||||
|
|
||||||
Typhoon is a minimal and free Kubernetes distribution.
|
Typhoon is a minimal and free Kubernetes distribution.
|
||||||
|
|
||||||
@ -9,30 +9,33 @@ Typhoon is a minimal and free Kubernetes distribution.
|
|||||||
|
|
||||||
Typhoon distributes upstream Kubernetes, architectural conventions, and cluster addons, much like a GNU/Linux distribution provides the Linux kernel and userspace components.
|
Typhoon distributes upstream Kubernetes, architectural conventions, and cluster addons, much like a GNU/Linux distribution provides the Linux kernel and userspace components.
|
||||||
|
|
||||||
## Features
|
## Features <a href="https://www.cncf.io/certification/software-conformance/"><img align="right" src="https://storage.googleapis.com/poseidon/certified-kubernetes.png"></a>
|
||||||
|
|
||||||
* Kubernetes v1.7.3 (upstream, via [kubernetes-incubator/bootkube](https://github.com/kubernetes-incubator/bootkube))
|
* Kubernetes v1.8.6 (upstream, via [kubernetes-incubator/bootkube](https://github.com/kubernetes-incubator/bootkube))
|
||||||
* Self-hosted control plane, single or multi master, workloads isolated to workers
|
* Single or multi-master, workloads isolated on workers, [Calico](https://www.projectcalico.org/) or [flannel](https://github.com/coreos/flannel) networking
|
||||||
* On-cluster etcd with TLS, [RBAC](https://kubernetes.io/docs/admin/authorization/rbac/)-enabled
|
* On-cluster etcd with TLS, [RBAC](https://kubernetes.io/docs/admin/authorization/rbac/)-enabled, [network policy](https://kubernetes.io/docs/concepts/services-networking/network-policies/)
|
||||||
* Ready for Ingress, Metrics, Dashboards, and other optional [addons](https://typhoon.psdn.io/addons/overview/)
|
* Ready for Ingress, Dashboards, Metrics, and other optional [addons](https://typhoon.psdn.io/addons/overview/)
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
Typhoon provides a Terraform Module for each supported operating system and platform.
|
Typhoon provides a Terraform Module for each supported operating system and platform.
|
||||||
|
|
||||||
| Platform | Operating System | Terraform Module |
|
| Platform | Operating System | Terraform Module | Status |
|
||||||
|---------------|------------------|------------------|
|
|---------------|------------------|------------------|--------|
|
||||||
| Bare-Metal | Container Linux | [bare-metal/container-linux/kubernetes](bare-metal/container-linux/kubernetes) |
|
| AWS | Container Linux | [aws/container-linux/kubernetes](aws/container-linux/kubernetes) | beta |
|
||||||
| Digital Ocean | Container Linux | [digital-ocean/container-linux/kubernetes](digital-ocean/container-linux/kubernetes) |
|
| Bare-Metal | Container Linux | [bare-metal/container-linux/kubernetes](bare-metal/container-linux/kubernetes) | stable |
|
||||||
| Google Cloud | Container Linux | [google-cloud/container-linux/kubernetes](google-cloud/container-linux/kubernetes) |
|
| Digital Ocean | Container Linux | [digital-ocean/container-linux/kubernetes](digital-ocean/container-linux/kubernetes) | beta |
|
||||||
|
| Google Cloud | Container Linux | [google-cloud/container-linux/kubernetes](google-cloud/container-linux/kubernetes) | beta |
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
* [Docs](https://typhoon.psdn.io)
|
* [Docs](https://typhoon.psdn.io)
|
||||||
* [Concepts](https://typhoon.psdn.io/concepts/)
|
* [Concepts](https://typhoon.psdn.io/concepts/)
|
||||||
* [Bare-Metal](https://typhoon.psdn.io/bare-metal/)
|
* Tutorials
|
||||||
* [Digital Ocean](https://typhoon.psdn.io/digital-ocean/)
|
* [AWS](https://typhoon.psdn.io/aws/)
|
||||||
* [Google-Cloud](https://typhoon.psdn.io/google-cloud/)
|
* [Bare-Metal](https://typhoon.psdn.io/bare-metal/)
|
||||||
|
* [Digital Ocean](https://typhoon.psdn.io/digital-ocean/)
|
||||||
|
* [Google-Cloud](https://typhoon.psdn.io/google-cloud/)
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
@ -43,10 +46,10 @@ module "google-cloud-yavin" {
|
|||||||
source = "git::https://github.com/poseidon/typhoon//google-cloud/container-linux/kubernetes"
|
source = "git::https://github.com/poseidon/typhoon//google-cloud/container-linux/kubernetes"
|
||||||
|
|
||||||
# Google Cloud
|
# Google Cloud
|
||||||
zone = "us-central1-c"
|
region = "us-central1"
|
||||||
dns_zone = "example.com"
|
dns_zone = "example.com"
|
||||||
dns_zone_name = "example-zone"
|
dns_zone_name = "example-zone"
|
||||||
os_image = "coreos-stable-1465-6-0-v20170817"
|
os_image = "coreos-stable-1576-4-0-v20171206"
|
||||||
|
|
||||||
cluster_name = "yavin"
|
cluster_name = "yavin"
|
||||||
controller_count = 1
|
controller_count = 1
|
||||||
@ -61,6 +64,7 @@ module "google-cloud-yavin" {
|
|||||||
Fetch modules, plan the changes to be made, and apply the changes.
|
Fetch modules, plan the changes to be made, and apply the changes.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
$ terraform init
|
||||||
$ terraform get --update
|
$ terraform get --update
|
||||||
$ terraform plan
|
$ terraform plan
|
||||||
Plan: 37 to add, 0 to change, 0 to destroy.
|
Plan: 37 to add, 0 to change, 0 to destroy.
|
||||||
@ -68,15 +72,15 @@ $ terraform apply
|
|||||||
Apply complete! Resources: 37 added, 0 changed, 0 destroyed.
|
Apply complete! Resources: 37 added, 0 changed, 0 destroyed.
|
||||||
```
|
```
|
||||||
|
|
||||||
In 5-10 minutes (varies by platform), the cluster will be ready. This Google Cloud example creates a `yavin.example.com` DNS record to resolve to a network load balancer across controller nodes.
|
In 4-8 minutes (varies by platform), the cluster will be ready. This Google Cloud example creates a `yavin.example.com` DNS record to resolve to a network load balancer across controller nodes.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ KUBECONFIG=/home/user/.secrets/clusters/yavin/auth/kubeconfig
|
$ KUBECONFIG=/home/user/.secrets/clusters/yavin/auth/kubeconfig
|
||||||
$ kubectl get nodes
|
$ kubectl get nodes
|
||||||
NAME STATUS AGE VERSION
|
NAME STATUS AGE VERSION
|
||||||
yavin-controller-1682.c.example-com.internal Ready 6m v1.7.3+coreos.0
|
yavin-controller-0.c.example-com.internal Ready 6m v1.8.6
|
||||||
yavin-worker-jrbf.c.example-com.internal Ready 5m v1.7.3+coreos.0
|
yavin-worker-jrbf.c.example-com.internal Ready 5m v1.8.6
|
||||||
yavin-worker-mzdm.c.example-com.internal Ready 5m v1.7.3+coreos.0
|
yavin-worker-mzdm.c.example-com.internal Ready 5m v1.8.6
|
||||||
```
|
```
|
||||||
|
|
||||||
List the pods.
|
List the pods.
|
||||||
@ -84,16 +88,13 @@ List the pods.
|
|||||||
```
|
```
|
||||||
$ kubectl get pods --all-namespaces
|
$ kubectl get pods --all-namespaces
|
||||||
NAMESPACE NAME READY STATUS RESTARTS AGE
|
NAMESPACE NAME READY STATUS RESTARTS AGE
|
||||||
kube-system etcd-operator-3329263108-f443m 1/1 Running 1 6m
|
kube-system calico-node-1cs8z 2/2 Running 0 6m
|
||||||
|
kube-system calico-node-d1l5b 2/2 Running 0 6m
|
||||||
|
kube-system calico-node-sp9ps 2/2 Running 0 6m
|
||||||
kube-system kube-apiserver-zppls 1/1 Running 0 6m
|
kube-system kube-apiserver-zppls 1/1 Running 0 6m
|
||||||
kube-system kube-controller-manager-3271970485-gh9kt 1/1 Running 0 6m
|
kube-system kube-controller-manager-3271970485-gh9kt 1/1 Running 0 6m
|
||||||
kube-system kube-controller-manager-3271970485-h90v8 1/1 Running 1 6m
|
kube-system kube-controller-manager-3271970485-h90v8 1/1 Running 1 6m
|
||||||
kube-system kube-dns-1187388186-zj5dl 3/3 Running 0 6m
|
kube-system kube-dns-1187388186-zj5dl 3/3 Running 0 6m
|
||||||
kube-system kube-etcd-0000 1/1 Running 0 5m
|
|
||||||
kube-system kube-etcd-network-checkpointer-crznb 1/1 Running 0 6m
|
|
||||||
kube-system kube-flannel-1cs8z 2/2 Running 0 6m
|
|
||||||
kube-system kube-flannel-d1l5b 2/2 Running 0 6m
|
|
||||||
kube-system kube-flannel-sp9ps 2/2 Running 0 6m
|
|
||||||
kube-system kube-proxy-117v6 1/1 Running 0 6m
|
kube-system kube-proxy-117v6 1/1 Running 0 6m
|
||||||
kube-system kube-proxy-9886n 1/1 Running 0 6m
|
kube-system kube-proxy-9886n 1/1 Running 0 6m
|
||||||
kube-system kube-proxy-njn47 1/1 Running 0 6m
|
kube-system kube-proxy-njn47 1/1 Running 0 6m
|
||||||
@ -110,6 +111,10 @@ Typhoon is strict about minimalism, maturity, and scope. These are not in scope:
|
|||||||
* Adding every possible option
|
* Adding every possible option
|
||||||
* Openstack or Mesos platforms
|
* Openstack or Mesos platforms
|
||||||
|
|
||||||
|
## Help
|
||||||
|
|
||||||
|
Ask questions on the IRC #typhoon channel on [freenode.net](http://freenode.net/).
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
Typhoon powers the author's cloud and colocation clusters. The project has evolved through operational experience and Kubernetes changes. Typhoon is shared under a free license to allow others to use the work freely and contribute to its upkeep.
|
Typhoon powers the author's cloud and colocation clusters. The project has evolved through operational experience and Kubernetes changes. Typhoon is shared under a free license to allow others to use the work freely and contribute to its upkeep.
|
||||||
|
12
addons/cluo/cluster-role-binding.yaml
Normal file
12
addons/cluo/cluster-role-binding.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: reboot-coordinator
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: reboot-coordinator
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
namespace: reboot-coordinator
|
||||||
|
name: default
|
45
addons/cluo/cluster-role.yaml
Normal file
45
addons/cluo/cluster-role.yaml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: reboot-coordinator
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- get
|
||||||
|
- update
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- events
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- delete
|
||||||
|
- apiGroups:
|
||||||
|
- "extensions"
|
||||||
|
resources:
|
||||||
|
- daemonsets
|
||||||
|
verbs:
|
||||||
|
- get
|
4
addons/cluo/namespace.yaml
Normal file
4
addons/cluo/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: reboot-coordinator
|
@ -2,7 +2,7 @@ apiVersion: extensions/v1beta1
|
|||||||
kind: DaemonSet
|
kind: DaemonSet
|
||||||
metadata:
|
metadata:
|
||||||
name: container-linux-update-agent
|
name: container-linux-update-agent
|
||||||
namespace: kube-system
|
namespace: reboot-coordinator
|
||||||
spec:
|
spec:
|
||||||
updateStrategy:
|
updateStrategy:
|
||||||
type: RollingUpdate
|
type: RollingUpdate
|
||||||
@ -15,7 +15,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: update-agent
|
- name: update-agent
|
||||||
image: quay.io/coreos/container-linux-update-operator:v0.3.1
|
image: quay.io/coreos/container-linux-update-operator:v0.4.1
|
||||||
command:
|
command:
|
||||||
- "/bin/update-agent"
|
- "/bin/update-agent"
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
|
@ -2,7 +2,7 @@ apiVersion: extensions/v1beta1
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: container-linux-update-operator
|
name: container-linux-update-operator
|
||||||
namespace: kube-system
|
namespace: reboot-coordinator
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
template:
|
template:
|
||||||
@ -12,12 +12,15 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: update-operator
|
- name: update-operator
|
||||||
image: quay.io/coreos/container-linux-update-operator:v0.3.1
|
image: quay.io/coreos/container-linux-update-operator:v0.4.1
|
||||||
command:
|
command:
|
||||||
- "/bin/update-operator"
|
- "/bin/update-operator"
|
||||||
- "--analytics=false"
|
|
||||||
env:
|
env:
|
||||||
- name: POD_NAMESPACE
|
- name: POD_NAMESPACE
|
||||||
valueFrom:
|
valueFrom:
|
||||||
fieldRef:
|
fieldRef:
|
||||||
fieldPath: metadata.namespace
|
fieldPath: metadata.namespace
|
||||||
|
tolerations:
|
||||||
|
- key: node-role.kubernetes.io/master
|
||||||
|
operator: Exists
|
||||||
|
effect: NoSchedule
|
||||||
|
46
addons/grafana/deployment.yaml
Normal file
46
addons/grafana/deployment.yaml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
apiVersion: apps/v1beta2
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: grafana
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
rollingUpdate:
|
||||||
|
maxUnavailable: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
name: grafana
|
||||||
|
phase: prod
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: grafana
|
||||||
|
phase: prod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: grafana
|
||||||
|
image: grafana/grafana:4.6.3
|
||||||
|
env:
|
||||||
|
- name: GF_SERVER_HTTP_PORT
|
||||||
|
value: "8080"
|
||||||
|
- name: GF_AUTH_BASIC_ENABLED
|
||||||
|
value: "false"
|
||||||
|
- name: GF_AUTH_ANONYMOUS_ENABLED
|
||||||
|
value: "true"
|
||||||
|
- name: GF_AUTH_ANONYMOUS_ORG_ROLE
|
||||||
|
value: Admin
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8080
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: 100Mi
|
||||||
|
cpu: 100m
|
||||||
|
limits:
|
||||||
|
memory: 200Mi
|
||||||
|
cpu: 200m
|
||||||
|
volumes:
|
||||||
|
- name: grafana-storage
|
||||||
|
emptyDir: {}
|
15
addons/grafana/service.yaml
Normal file
15
addons/grafana/service.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: grafana
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
name: grafana
|
||||||
|
phase: prod
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
@ -1,29 +1,25 @@
|
|||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1beta2
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: heapster
|
name: heapster
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
labels:
|
|
||||||
k8s-app: heapster
|
|
||||||
kubernetes.io/cluster-service: "true"
|
|
||||||
version: v1.4.0
|
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
k8s-app: heapster
|
name: heapster
|
||||||
version: v1.4.0
|
phase: prod
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
k8s-app: heapster
|
name: heapster
|
||||||
version: v1.4.0
|
phase: prod
|
||||||
annotations:
|
annotations:
|
||||||
scheduler.alpha.kubernetes.io/critical-pod: ''
|
scheduler.alpha.kubernetes.io/critical-pod: ''
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: heapster
|
- name: heapster
|
||||||
image: gcr.io/google_containers/heapster-amd64:v1.4.0
|
image: gcr.io/google_containers/heapster-amd64:v1.5.0
|
||||||
command:
|
command:
|
||||||
- /heapster
|
- /heapster
|
||||||
- --source=kubernetes.summary_api:''
|
- --source=kubernetes.summary_api:''
|
||||||
@ -35,16 +31,18 @@ spec:
|
|||||||
initialDelaySeconds: 180
|
initialDelaySeconds: 180
|
||||||
timeoutSeconds: 5
|
timeoutSeconds: 5
|
||||||
- name: heapster-nanny
|
- name: heapster-nanny
|
||||||
image: gcr.io/google_containers/addon-resizer:2.0
|
image: gcr.io/google_containers/addon-resizer:1.7
|
||||||
command:
|
command:
|
||||||
- /pod_nanny
|
- /pod_nanny
|
||||||
- --cpu=80m
|
- --cpu=80m
|
||||||
- --extra-cpu=0.5m
|
- --extra-cpu=0.5m
|
||||||
- --memory=140Mi
|
- --memory=140Mi
|
||||||
- --extra-memory=4Mi
|
- --extra-memory=4Mi
|
||||||
- --deployment=heapster-v1.4.0
|
- --threshold=5
|
||||||
|
- --deployment=heapster
|
||||||
- --container=heapster
|
- --container=heapster
|
||||||
- --poll-period=300000
|
- --poll-period=300000
|
||||||
|
- --estimator=exponential
|
||||||
env:
|
env:
|
||||||
- name: MY_POD_NAME
|
- name: MY_POD_NAME
|
||||||
valueFrom:
|
valueFrom:
|
||||||
|
@ -3,13 +3,10 @@ kind: Service
|
|||||||
metadata:
|
metadata:
|
||||||
name: heapster
|
name: heapster
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
labels:
|
|
||||||
kubernetes.io/cluster-service: "true"
|
|
||||||
kubernetes.io/name: "Heapster"
|
|
||||||
spec:
|
spec:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
selector:
|
selector:
|
||||||
k8s-app: heapster
|
name: heapster
|
||||||
ports:
|
ports:
|
||||||
- port: 80
|
- port: 80
|
||||||
targetPort: 8082
|
targetPort: 8082
|
||||||
|
36
addons/nginx-ingress/aws/default-backend/deployment.yaml
Normal file
36
addons/nginx-ingress/aws/default-backend/deployment.yaml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: default-backend
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: default-backend
|
||||||
|
phase: prod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: default-backend
|
||||||
|
# Any image is permissable as long as:
|
||||||
|
# 1. It serves a 404 page at /
|
||||||
|
# 2. It serves 200 on a /healthz endpoint
|
||||||
|
image: gcr.io/google_containers/defaultbackend:1.4
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 10m
|
||||||
|
memory: 20Mi
|
||||||
|
requests:
|
||||||
|
cpu: 10m
|
||||||
|
memory: 20Mi
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 8080
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
terminationGracePeriodSeconds: 60
|
15
addons/nginx-ingress/aws/default-backend/service.yaml
Normal file
15
addons/nginx-ingress/aws/default-backend/service.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: default-backend
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
name: default-backend
|
||||||
|
phase: prod
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
67
addons/nginx-ingress/aws/deployment.yaml
Normal file
67
addons/nginx-ingress/aws/deployment.yaml
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxUnavailable: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
phase: prod
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
node-role.kubernetes.io/node: ""
|
||||||
|
hostNetwork: true
|
||||||
|
containers:
|
||||||
|
- name: nginx-ingress-controller
|
||||||
|
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.9.0
|
||||||
|
args:
|
||||||
|
- /nginx-ingress-controller
|
||||||
|
- --default-backend-service=$(POD_NAMESPACE)/default-backend
|
||||||
|
- --ingress-class=public
|
||||||
|
# use downward API
|
||||||
|
env:
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
|
hostPort: 80
|
||||||
|
- name: https
|
||||||
|
containerPort: 443
|
||||||
|
hostPort: 443
|
||||||
|
- name: health
|
||||||
|
containerPort: 10254
|
||||||
|
hostPort: 10254
|
||||||
|
livenessProbe:
|
||||||
|
failureThreshold: 3
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 10254
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 1
|
||||||
|
readinessProbe:
|
||||||
|
failureThreshold: 3
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 10254
|
||||||
|
scheme: HTTP
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 1
|
||||||
|
restartPolicy: Always
|
||||||
|
terminationGracePeriodSeconds: 60
|
4
addons/nginx-ingress/aws/namespace.yaml
Normal file
4
addons/nginx-ingress/aws/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
12
addons/nginx-ingress/aws/rbac/cluster-role-binding.yaml
Normal file
12
addons/nginx-ingress/aws/rbac/cluster-role-binding.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: ingress
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
namespace: ingress
|
||||||
|
name: default
|
51
addons/nginx-ingress/aws/rbac/cluster-role.yaml
Normal file
51
addons/nginx-ingress/aws/rbac/cluster-role.yaml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- endpoints
|
||||||
|
- nodes
|
||||||
|
- pods
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- "extensions"
|
||||||
|
resources:
|
||||||
|
- ingresses
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- events
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- patch
|
||||||
|
- apiGroups:
|
||||||
|
- "extensions"
|
||||||
|
resources:
|
||||||
|
- ingresses/status
|
||||||
|
verbs:
|
||||||
|
- update
|
13
addons/nginx-ingress/aws/rbac/role-binding.yaml
Normal file
13
addons/nginx-ingress/aws/rbac/role-binding.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
namespace: ingress
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: ingress
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
namespace: ingress
|
||||||
|
name: default
|
41
addons/nginx-ingress/aws/rbac/role.yaml
Normal file
41
addons/nginx-ingress/aws/rbac/role.yaml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
namespace: ingress
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- pods
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
resourceNames:
|
||||||
|
# Defaults to "<election-id>-<ingress-class>"
|
||||||
|
# Here: "<ingress-controller-leader>-<nginx>"
|
||||||
|
# This has to be adapted if you change either parameter
|
||||||
|
# when launching the nginx-ingress-controller.
|
||||||
|
- "ingress-controller-leader-public"
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- endpoints
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- create
|
||||||
|
- update
|
19
addons/nginx-ingress/aws/service.yaml
Normal file
19
addons/nginx-ingress/aws/service.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
phase: prod
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
- name: https
|
||||||
|
protocol: TCP
|
||||||
|
port: 443
|
||||||
|
targetPort: 443
|
67
addons/nginx-ingress/digital-ocean/daemonset.yaml
Normal file
67
addons/nginx-ingress/digital-ocean/daemonset.yaml
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: DaemonSet
|
||||||
|
metadata:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
updateStrategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
rollingUpdate:
|
||||||
|
maxUnavailable: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
phase: prod
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
node-role.kubernetes.io/node: ""
|
||||||
|
hostNetwork: true
|
||||||
|
containers:
|
||||||
|
- name: nginx-ingress-controller
|
||||||
|
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.9.0
|
||||||
|
args:
|
||||||
|
- /nginx-ingress-controller
|
||||||
|
- --default-backend-service=$(POD_NAMESPACE)/default-backend
|
||||||
|
- --ingress-class=public
|
||||||
|
# use downward API
|
||||||
|
env:
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
|
hostPort: 80
|
||||||
|
- name: https
|
||||||
|
containerPort: 443
|
||||||
|
hostPort: 443
|
||||||
|
- name: health
|
||||||
|
containerPort: 10254
|
||||||
|
hostPort: 10254
|
||||||
|
livenessProbe:
|
||||||
|
failureThreshold: 3
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 10254
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 1
|
||||||
|
readinessProbe:
|
||||||
|
failureThreshold: 3
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 10254
|
||||||
|
scheme: HTTP
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 1
|
||||||
|
restartPolicy: Always
|
||||||
|
terminationGracePeriodSeconds: 60
|
@ -0,0 +1,36 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: default-backend
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: default-backend
|
||||||
|
phase: prod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: default-backend
|
||||||
|
# Any image is permissable as long as:
|
||||||
|
# 1. It serves a 404 page at /
|
||||||
|
# 2. It serves 200 on a /healthz endpoint
|
||||||
|
image: gcr.io/google_containers/defaultbackend:1.4
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 10m
|
||||||
|
memory: 20Mi
|
||||||
|
requests:
|
||||||
|
cpu: 10m
|
||||||
|
memory: 20Mi
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 8080
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
terminationGracePeriodSeconds: 60
|
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: default-backend
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
name: default-backend
|
||||||
|
phase: prod
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
4
addons/nginx-ingress/digital-ocean/namespace.yaml
Normal file
4
addons/nginx-ingress/digital-ocean/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
@ -0,0 +1,12 @@
|
|||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: ingress
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
namespace: ingress
|
||||||
|
name: default
|
51
addons/nginx-ingress/digital-ocean/rbac/cluster-role.yaml
Normal file
51
addons/nginx-ingress/digital-ocean/rbac/cluster-role.yaml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- endpoints
|
||||||
|
- nodes
|
||||||
|
- pods
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- "extensions"
|
||||||
|
resources:
|
||||||
|
- ingresses
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- events
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- patch
|
||||||
|
- apiGroups:
|
||||||
|
- "extensions"
|
||||||
|
resources:
|
||||||
|
- ingresses/status
|
||||||
|
verbs:
|
||||||
|
- update
|
13
addons/nginx-ingress/digital-ocean/rbac/role-binding.yaml
Normal file
13
addons/nginx-ingress/digital-ocean/rbac/role-binding.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
namespace: ingress
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: ingress
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
namespace: ingress
|
||||||
|
name: default
|
41
addons/nginx-ingress/digital-ocean/rbac/role.yaml
Normal file
41
addons/nginx-ingress/digital-ocean/rbac/role.yaml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
namespace: ingress
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- pods
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
resourceNames:
|
||||||
|
# Defaults to "<election-id>-<ingress-class>"
|
||||||
|
# Here: "<ingress-controller-leader>-<nginx>"
|
||||||
|
# This has to be adapted if you change either parameter
|
||||||
|
# when launching the nginx-ingress-controller.
|
||||||
|
- "ingress-controller-leader-public"
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- endpoints
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- create
|
||||||
|
- update
|
19
addons/nginx-ingress/digital-ocean/service.yaml
Normal file
19
addons/nginx-ingress/digital-ocean/service.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
phase: prod
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
- name: https
|
||||||
|
protocol: TCP
|
||||||
|
port: 443
|
||||||
|
targetPort: 443
|
@ -0,0 +1,36 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: default-backend
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: default-backend
|
||||||
|
phase: prod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: default-backend
|
||||||
|
# Any image is permissable as long as:
|
||||||
|
# 1. It serves a 404 page at /
|
||||||
|
# 2. It serves 200 on a /healthz endpoint
|
||||||
|
image: gcr.io/google_containers/defaultbackend:1.4
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 10m
|
||||||
|
memory: 20Mi
|
||||||
|
requests:
|
||||||
|
cpu: 10m
|
||||||
|
memory: 20Mi
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 8080
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
terminationGracePeriodSeconds: 60
|
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: default-backend
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
name: default-backend
|
||||||
|
phase: prod
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
67
addons/nginx-ingress/google-cloud/deployment.yaml
Normal file
67
addons/nginx-ingress/google-cloud/deployment.yaml
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxUnavailable: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
phase: prod
|
||||||
|
spec:
|
||||||
|
nodeSelector:
|
||||||
|
node-role.kubernetes.io/node: ""
|
||||||
|
hostNetwork: true
|
||||||
|
containers:
|
||||||
|
- name: nginx-ingress-controller
|
||||||
|
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.9.0
|
||||||
|
args:
|
||||||
|
- /nginx-ingress-controller
|
||||||
|
- --default-backend-service=$(POD_NAMESPACE)/default-backend
|
||||||
|
- --ingress-class=public
|
||||||
|
# use downward API
|
||||||
|
env:
|
||||||
|
- name: POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
- name: POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 80
|
||||||
|
hostPort: 80
|
||||||
|
- name: https
|
||||||
|
containerPort: 443
|
||||||
|
hostPort: 443
|
||||||
|
- name: health
|
||||||
|
containerPort: 10254
|
||||||
|
hostPort: 10254
|
||||||
|
livenessProbe:
|
||||||
|
failureThreshold: 3
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 10254
|
||||||
|
scheme: HTTP
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 1
|
||||||
|
readinessProbe:
|
||||||
|
failureThreshold: 3
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 10254
|
||||||
|
scheme: HTTP
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 1
|
||||||
|
restartPolicy: Always
|
||||||
|
terminationGracePeriodSeconds: 60
|
4
addons/nginx-ingress/google-cloud/namespace.yaml
Normal file
4
addons/nginx-ingress/google-cloud/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
@ -0,0 +1,12 @@
|
|||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: ingress
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
namespace: ingress
|
||||||
|
name: default
|
51
addons/nginx-ingress/google-cloud/rbac/cluster-role.yaml
Normal file
51
addons/nginx-ingress/google-cloud/rbac/cluster-role.yaml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- endpoints
|
||||||
|
- nodes
|
||||||
|
- pods
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- "extensions"
|
||||||
|
resources:
|
||||||
|
- ingresses
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- events
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- patch
|
||||||
|
- apiGroups:
|
||||||
|
- "extensions"
|
||||||
|
resources:
|
||||||
|
- ingresses/status
|
||||||
|
verbs:
|
||||||
|
- update
|
13
addons/nginx-ingress/google-cloud/rbac/role-binding.yaml
Normal file
13
addons/nginx-ingress/google-cloud/rbac/role-binding.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
kind: RoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
namespace: ingress
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: ingress
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
namespace: ingress
|
||||||
|
name: default
|
41
addons/nginx-ingress/google-cloud/rbac/role.yaml
Normal file
41
addons/nginx-ingress/google-cloud/rbac/role.yaml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
kind: Role
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ingress
|
||||||
|
namespace: ingress
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
- pods
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
resourceNames:
|
||||||
|
# Defaults to "<election-id>-<ingress-class>"
|
||||||
|
# Here: "<ingress-controller-leader>-<nginx>"
|
||||||
|
# This has to be adapted if you change either parameter
|
||||||
|
# when launching the nginx-ingress-controller.
|
||||||
|
- "ingress-controller-leader-public"
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- endpoints
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- create
|
||||||
|
- update
|
19
addons/nginx-ingress/google-cloud/service.yaml
Normal file
19
addons/nginx-ingress/google-cloud/service.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
namespace: ingress
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
name: nginx-ingress-controller
|
||||||
|
phase: prod
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
- name: https
|
||||||
|
protocol: TCP
|
||||||
|
port: 443
|
||||||
|
targetPort: 443
|
226
addons/prometheus/config.yaml
Normal file
226
addons/prometheus/config.yaml
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: prometheus-config
|
||||||
|
namespace: monitoring
|
||||||
|
data:
|
||||||
|
prometheus.yaml: |-
|
||||||
|
# Global config
|
||||||
|
global:
|
||||||
|
scrape_interval: 15s
|
||||||
|
|
||||||
|
# AlertManager
|
||||||
|
alerting:
|
||||||
|
alertmanagers:
|
||||||
|
- static_configs:
|
||||||
|
- targets:
|
||||||
|
- alertmanager:9093
|
||||||
|
|
||||||
|
# Scrape configs for running Prometheus on a Kubernetes cluster.
|
||||||
|
# This uses separate scrape configs for cluster components (i.e. API server, node)
|
||||||
|
# and services to allow each to use different authentication configs.
|
||||||
|
#
|
||||||
|
# Kubernetes labels will be added as Prometheus labels on metrics via the
|
||||||
|
# `labelmap` relabeling action.
|
||||||
|
scrape_configs:
|
||||||
|
|
||||||
|
# Scrape config for API servers.
|
||||||
|
#
|
||||||
|
# Kubernetes exposes API servers as endpoints to the default/kubernetes
|
||||||
|
# service so this uses `endpoints` role and uses relabelling to only keep
|
||||||
|
# the endpoints associated with the default/kubernetes service using the
|
||||||
|
# default named port `https`. This works for single API server deployments as
|
||||||
|
# well as HA API server deployments.
|
||||||
|
- job_name: 'kubernetes-apiservers'
|
||||||
|
kubernetes_sd_configs:
|
||||||
|
- role: endpoints
|
||||||
|
|
||||||
|
scheme: https
|
||||||
|
tls_config:
|
||||||
|
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||||
|
# Using endpoints to discover kube-apiserver targets finds the pod IP
|
||||||
|
# (host IP since apiserver is uses host network) which is not used in
|
||||||
|
# the server certificate.
|
||||||
|
insecure_skip_verify: true
|
||||||
|
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||||
|
|
||||||
|
# Keep only the default/kubernetes service endpoints for the https port. This
|
||||||
|
# will add targets for each API server which Kubernetes adds an endpoint to
|
||||||
|
# the default/kubernetes service.
|
||||||
|
relabel_configs:
|
||||||
|
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
|
||||||
|
action: keep
|
||||||
|
regex: default;kubernetes;https
|
||||||
|
|
||||||
|
# Scrape config for node (i.e. kubelet) /metrics (e.g. 'kubelet_'). Explore
|
||||||
|
# metrics from a node by scraping kubelet (127.0.0.1:10255/metrics).
|
||||||
|
#
|
||||||
|
# Rather than connecting directly to the node, the scrape is proxied though the
|
||||||
|
# Kubernetes apiserver. This means it will work if Prometheus is running out of
|
||||||
|
# cluster, or can't connect to nodes for some other reason (e.g. because of
|
||||||
|
# firewalling).
|
||||||
|
- job_name: 'kubernetes-nodes'
|
||||||
|
kubernetes_sd_configs:
|
||||||
|
- role: node
|
||||||
|
|
||||||
|
scheme: https
|
||||||
|
tls_config:
|
||||||
|
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||||
|
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||||
|
|
||||||
|
relabel_configs:
|
||||||
|
- action: labelmap
|
||||||
|
regex: __meta_kubernetes_node_label_(.+)
|
||||||
|
- target_label: __address__
|
||||||
|
replacement: kubernetes.default.svc:443
|
||||||
|
- source_labels: [__meta_kubernetes_node_name]
|
||||||
|
regex: (.+)
|
||||||
|
target_label: __metrics_path__
|
||||||
|
replacement: /api/v1/nodes/${1}/proxy/metrics
|
||||||
|
|
||||||
|
# Scrape config for Kubelet cAdvisor. Explore metrics from a node by
|
||||||
|
# scraping kubelet (127.0.0.1:10255/metrics/cadvisor).
|
||||||
|
#
|
||||||
|
# This is required for Kubernetes 1.7.3 and later, where cAdvisor metrics
|
||||||
|
# (those whose names begin with 'container_') have been removed from the
|
||||||
|
# Kubelet metrics endpoint. This job scrapes the cAdvisor endpoint to
|
||||||
|
# retrieve those metrics.
|
||||||
|
#
|
||||||
|
# Rather than connecting directly to the node, the scrape is proxied though the
|
||||||
|
# Kubernetes apiserver. This means it will work if Prometheus is running out of
|
||||||
|
# cluster, or can't connect to nodes for some other reason (e.g. because of
|
||||||
|
# firewalling).
|
||||||
|
- job_name: 'kubernetes-cadvisor'
|
||||||
|
kubernetes_sd_configs:
|
||||||
|
- role: node
|
||||||
|
|
||||||
|
scheme: https
|
||||||
|
tls_config:
|
||||||
|
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||||
|
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||||
|
|
||||||
|
relabel_configs:
|
||||||
|
- action: labelmap
|
||||||
|
regex: __meta_kubernetes_node_label_(.+)
|
||||||
|
- target_label: __address__
|
||||||
|
replacement: kubernetes.default.svc:443
|
||||||
|
- source_labels: [__meta_kubernetes_node_name]
|
||||||
|
regex: (.+)
|
||||||
|
target_label: __metrics_path__
|
||||||
|
replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
|
||||||
|
|
||||||
|
# Scrape config for service endpoints.
|
||||||
|
#
|
||||||
|
# The relabeling allows the actual service scrape endpoint to be configured
|
||||||
|
# via the following annotations:
|
||||||
|
#
|
||||||
|
# * `prometheus.io/scrape`: Only scrape services that have a value of `true`
|
||||||
|
# * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need
|
||||||
|
# to set this to `https` & most likely set the `tls_config` of the scrape config.
|
||||||
|
# * `prometheus.io/path`: If the metrics path is not `/metrics` override this.
|
||||||
|
# * `prometheus.io/port`: If the metrics are exposed on a different port to the
|
||||||
|
# service then set this appropriately.
|
||||||
|
- job_name: 'kubernetes-service-endpoints'
|
||||||
|
|
||||||
|
kubernetes_sd_configs:
|
||||||
|
- role: endpoints
|
||||||
|
|
||||||
|
relabel_configs:
|
||||||
|
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
|
||||||
|
action: keep
|
||||||
|
regex: true
|
||||||
|
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
|
||||||
|
action: replace
|
||||||
|
target_label: __scheme__
|
||||||
|
regex: (https?)
|
||||||
|
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
|
||||||
|
action: replace
|
||||||
|
target_label: __metrics_path__
|
||||||
|
regex: (.+)
|
||||||
|
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
|
||||||
|
action: replace
|
||||||
|
target_label: __address__
|
||||||
|
regex: ([^:]+)(?::\d+)?;(\d+)
|
||||||
|
replacement: $1:$2
|
||||||
|
- action: labelmap
|
||||||
|
regex: __meta_kubernetes_service_label_(.+)
|
||||||
|
- source_labels: [__meta_kubernetes_namespace]
|
||||||
|
action: replace
|
||||||
|
target_label: kubernetes_namespace
|
||||||
|
- source_labels: [__meta_kubernetes_service_name]
|
||||||
|
action: replace
|
||||||
|
target_label: kubernetes_name
|
||||||
|
|
||||||
|
# Example scrape config for probing services via the Blackbox Exporter.
|
||||||
|
#
|
||||||
|
# The relabeling allows the actual service scrape endpoint to be configured
|
||||||
|
# via the following annotations:
|
||||||
|
#
|
||||||
|
# * `prometheus.io/probe`: Only probe services that have a value of `true`
|
||||||
|
- job_name: 'kubernetes-services'
|
||||||
|
|
||||||
|
metrics_path: /probe
|
||||||
|
params:
|
||||||
|
module: [http_2xx]
|
||||||
|
|
||||||
|
kubernetes_sd_configs:
|
||||||
|
- role: service
|
||||||
|
|
||||||
|
relabel_configs:
|
||||||
|
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe]
|
||||||
|
action: keep
|
||||||
|
regex: true
|
||||||
|
- source_labels: [__address__]
|
||||||
|
target_label: __param_target
|
||||||
|
- target_label: __address__
|
||||||
|
replacement: blackbox
|
||||||
|
- source_labels: [__param_target]
|
||||||
|
target_label: instance
|
||||||
|
- action: labelmap
|
||||||
|
regex: __meta_kubernetes_service_label_(.+)
|
||||||
|
- source_labels: [__meta_kubernetes_namespace]
|
||||||
|
target_label: kubernetes_namespace
|
||||||
|
- source_labels: [__meta_kubernetes_service_name]
|
||||||
|
target_label: kubernetes_name
|
||||||
|
|
||||||
|
# Example scrape config for pods
|
||||||
|
#
|
||||||
|
# The relabeling allows the actual pod scrape endpoint to be configured via the
|
||||||
|
# following annotations:
|
||||||
|
#
|
||||||
|
# * `prometheus.io/scrape`: Only scrape pods that have a value of `true`
|
||||||
|
# * `prometheus.io/path`: If the metrics path is not `/metrics` override this.
|
||||||
|
# * `prometheus.io/port`: Scrape the pod on the indicated port instead of the
|
||||||
|
# pod's declared ports (default is a port-free target if none are declared).
|
||||||
|
- job_name: 'kubernetes-pods'
|
||||||
|
|
||||||
|
kubernetes_sd_configs:
|
||||||
|
- role: pod
|
||||||
|
|
||||||
|
relabel_configs:
|
||||||
|
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
|
||||||
|
action: keep
|
||||||
|
regex: true
|
||||||
|
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
|
||||||
|
action: replace
|
||||||
|
target_label: __metrics_path__
|
||||||
|
regex: (.+)
|
||||||
|
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
|
||||||
|
action: replace
|
||||||
|
regex: ([^:]+)(?::\d+)?;(\d+)
|
||||||
|
replacement: $1:$2
|
||||||
|
target_label: __address__
|
||||||
|
- action: labelmap
|
||||||
|
regex: __meta_kubernetes_pod_label_(.+)
|
||||||
|
- source_labels: [__meta_kubernetes_namespace]
|
||||||
|
action: replace
|
||||||
|
target_label: kubernetes_namespace
|
||||||
|
- source_labels: [__meta_kubernetes_pod_name]
|
||||||
|
action: replace
|
||||||
|
target_label: kubernetes_pod_name
|
||||||
|
|
||||||
|
# Rule files
|
||||||
|
rule_files:
|
||||||
|
- "/etc/prometheus/rules/*.rules"
|
||||||
|
- "/etc/prometheus/rules/*.yaml"
|
||||||
|
- "/etc/prometheus/rules/*.yml"
|
43
addons/prometheus/deployment.yaml
Normal file
43
addons/prometheus/deployment.yaml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: prometheus
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxUnavailable: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: prometheus
|
||||||
|
phase: prod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: prometheus
|
||||||
|
image: quay.io/prometheus/prometheus:v2.0.0
|
||||||
|
args:
|
||||||
|
- '--config.file=/etc/prometheus/prometheus.yaml'
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
containerPort: 9090
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /etc/prometheus
|
||||||
|
- name: rules
|
||||||
|
mountPath: /etc/prometheus/rules
|
||||||
|
- name: data
|
||||||
|
mountPath: /var/lib/prometheus
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
|
terminationGracePeriodSeconds: 30
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: prometheus-config
|
||||||
|
- name: rules
|
||||||
|
configMap:
|
||||||
|
name: prometheus-rules
|
||||||
|
- name: data
|
||||||
|
emptyDir: {}
|
18
addons/prometheus/discovery/kube-controller-manager.yaml
Normal file
18
addons/prometheus/discovery/kube-controller-manager.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: kube-controller-manager
|
||||||
|
namespace: kube-system
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: 'true'
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
# service is created to allow prometheus to scrape endpoints
|
||||||
|
clusterIP: None
|
||||||
|
selector:
|
||||||
|
k8s-app: kube-controller-manager
|
||||||
|
ports:
|
||||||
|
- name: metrics
|
||||||
|
protocol: TCP
|
||||||
|
port: 10252
|
||||||
|
targetPort: 10252
|
18
addons/prometheus/discovery/kube-scheduler.yaml
Normal file
18
addons/prometheus/discovery/kube-scheduler.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: kube-scheduler
|
||||||
|
namespace: kube-system
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: 'true'
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
# service is created to allow prometheus to scrape endpoints
|
||||||
|
clusterIP: None
|
||||||
|
selector:
|
||||||
|
k8s-app: kube-scheduler
|
||||||
|
ports:
|
||||||
|
- name: metrics
|
||||||
|
protocol: TCP
|
||||||
|
port: 10251
|
||||||
|
targetPort: 10251
|
@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: kube-state-metrics
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: kube-state-metrics
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kube-state-metrics
|
||||||
|
namespace: monitoring
|
@ -0,0 +1,31 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: kube-state-metrics
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
- pods
|
||||||
|
- services
|
||||||
|
- resourcequotas
|
||||||
|
- replicationcontrollers
|
||||||
|
- limitranges
|
||||||
|
- persistentvolumeclaims
|
||||||
|
- namespaces
|
||||||
|
verbs: ["list", "watch"]
|
||||||
|
- apiGroups: ["extensions"]
|
||||||
|
resources:
|
||||||
|
- daemonsets
|
||||||
|
- deployments
|
||||||
|
- replicasets
|
||||||
|
verbs: ["list", "watch"]
|
||||||
|
- apiGroups: ["apps"]
|
||||||
|
resources:
|
||||||
|
- statefulsets
|
||||||
|
verbs: ["list", "watch"]
|
||||||
|
- apiGroups: ["batch"]
|
||||||
|
resources:
|
||||||
|
- cronjobs
|
||||||
|
- jobs
|
||||||
|
verbs: ["list", "watch"]
|
@ -0,0 +1,61 @@
|
|||||||
|
apiVersion: apps/v1beta2
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: kube-state-metrics
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
rollingUpdate:
|
||||||
|
maxUnavailable: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
name: kube-state-metrics
|
||||||
|
phase: prod
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: kube-state-metrics
|
||||||
|
phase: prod
|
||||||
|
spec:
|
||||||
|
serviceAccountName: kube-state-metrics
|
||||||
|
containers:
|
||||||
|
- name: kube-state-metrics
|
||||||
|
image: quay.io/coreos/kube-state-metrics:v1.1.0
|
||||||
|
ports:
|
||||||
|
- name: metrics
|
||||||
|
containerPort: 8080
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /healthz
|
||||||
|
port: 8080
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
timeoutSeconds: 5
|
||||||
|
- name: addon-resizer
|
||||||
|
image: gcr.io/google_containers/addon-resizer:1.0
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 30Mi
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 30Mi
|
||||||
|
env:
|
||||||
|
- name: MY_POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
- name: MY_POD_NAMESPACE
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.namespace
|
||||||
|
command:
|
||||||
|
- /pod_nanny
|
||||||
|
- --container=kube-state-metrics
|
||||||
|
- --cpu=100m
|
||||||
|
- --extra-cpu=1m
|
||||||
|
- --memory=100Mi
|
||||||
|
- --extra-memory=2Mi
|
||||||
|
- --threshold=5
|
||||||
|
- --deployment=kube-state-metrics
|
@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: kube-state-metrics
|
||||||
|
namespace: monitoring
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: kube-state-metrics-resizer
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: kube-state-metrics
|
||||||
|
namespace: monitoring
|
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: kube-state-metrics-resizer
|
||||||
|
namespace: monitoring
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources:
|
||||||
|
- pods
|
||||||
|
verbs: ["get"]
|
||||||
|
- apiGroups: ["extensions"]
|
||||||
|
resources:
|
||||||
|
- deployments
|
||||||
|
resourceNames: ["kube-state-metrics"]
|
||||||
|
verbs: ["get", "update"]
|
@ -0,0 +1,5 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: kube-state-metrics
|
||||||
|
namespace: monitoring
|
19
addons/prometheus/exporters/kube-state-metrics/service.yaml
Normal file
19
addons/prometheus/exporters/kube-state-metrics/service.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: kube-state-metrics
|
||||||
|
namespace: monitoring
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: 'true'
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
# service is created to allow prometheus to scape endpoints
|
||||||
|
clusterIP: None
|
||||||
|
selector:
|
||||||
|
name: kube-state-metrics
|
||||||
|
phase: prod
|
||||||
|
ports:
|
||||||
|
- name: metrics
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
57
addons/prometheus/exporters/node-exporter/daemonset.yaml
Normal file
57
addons/prometheus/exporters/node-exporter/daemonset.yaml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
apiVersion: apps/v1beta2
|
||||||
|
kind: DaemonSet
|
||||||
|
metadata:
|
||||||
|
name: node-exporter
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
updateStrategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
rollingUpdate:
|
||||||
|
maxUnavailable: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
name: node-exporter
|
||||||
|
phase: prod
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: node-exporter
|
||||||
|
phase: prod
|
||||||
|
spec:
|
||||||
|
hostNetwork: true
|
||||||
|
hostPID: true
|
||||||
|
containers:
|
||||||
|
- name: node-exporter
|
||||||
|
image: quay.io/prometheus/node-exporter:v0.15.0
|
||||||
|
args:
|
||||||
|
- "--path.procfs=/host/proc"
|
||||||
|
- "--path.sysfs=/host/sys"
|
||||||
|
ports:
|
||||||
|
- name: metrics
|
||||||
|
containerPort: 9100
|
||||||
|
hostPort: 9100
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: 30Mi
|
||||||
|
cpu: 100m
|
||||||
|
limits:
|
||||||
|
memory: 50Mi
|
||||||
|
cpu: 200m
|
||||||
|
volumeMounts:
|
||||||
|
- name: proc
|
||||||
|
mountPath: /host/proc
|
||||||
|
readOnly: true
|
||||||
|
- name: sys
|
||||||
|
mountPath: /host/sys
|
||||||
|
readOnly: true
|
||||||
|
tolerations:
|
||||||
|
- key: node-role.kubernetes.io/master
|
||||||
|
operator: Exists
|
||||||
|
effect: NoSchedule
|
||||||
|
volumes:
|
||||||
|
- name: proc
|
||||||
|
hostPath:
|
||||||
|
path: /proc
|
||||||
|
- name: sys
|
||||||
|
hostPath:
|
||||||
|
path: /sys
|
19
addons/prometheus/exporters/node-exporter/service.yaml
Normal file
19
addons/prometheus/exporters/node-exporter/service.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: node-exporter
|
||||||
|
namespace: monitoring
|
||||||
|
annotations:
|
||||||
|
prometheus.io/scrape: 'true'
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
# service is created to allow prometheus to scape endpoints
|
||||||
|
clusterIP: None
|
||||||
|
selector:
|
||||||
|
name: node-exporter
|
||||||
|
phase: prod
|
||||||
|
ports:
|
||||||
|
- name: metrics
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 9100
|
4
addons/prometheus/namespace.yaml
Normal file
4
addons/prometheus/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: monitoring
|
12
addons/prometheus/rbac/cluster-role-binding.yaml
Normal file
12
addons/prometheus/rbac/cluster-role-binding.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: prometheus
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: prometheus
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: default
|
||||||
|
namespace: monitoring
|
15
addons/prometheus/rbac/cluster-role.yaml
Normal file
15
addons/prometheus/rbac/cluster-role.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: prometheus
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources:
|
||||||
|
- nodes
|
||||||
|
- nodes/proxy
|
||||||
|
- services
|
||||||
|
- endpoints
|
||||||
|
- pods
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
- nonResourceURLs: ["/metrics"]
|
||||||
|
verbs: ["get"]
|
546
addons/prometheus/rules.yaml
Normal file
546
addons/prometheus/rules.yaml
Normal file
@ -0,0 +1,546 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: prometheus-rules
|
||||||
|
namespace: monitoring
|
||||||
|
data:
|
||||||
|
# Rules adapted from those provided by coreos/prometheus-operator and SoundCloud
|
||||||
|
alertmanager.rules.yaml: |+
|
||||||
|
groups:
|
||||||
|
- name: alertmanager.rules
|
||||||
|
rules:
|
||||||
|
- alert: AlertmanagerConfigInconsistent
|
||||||
|
expr: count_values("config_hash", alertmanager_config_hash) BY (service) / ON(service)
|
||||||
|
GROUP_LEFT() label_replace(prometheus_operator_alertmanager_spec_replicas, "service",
|
||||||
|
"alertmanager-$1", "alertmanager", "(.*)") != 1
|
||||||
|
for: 5m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: The configuration of the instances of the Alertmanager cluster
|
||||||
|
`{{$labels.service}}` are out of sync.
|
||||||
|
- alert: AlertmanagerDownOrMissing
|
||||||
|
expr: label_replace(prometheus_operator_alertmanager_spec_replicas, "job", "alertmanager-$1",
|
||||||
|
"alertmanager", "(.*)") / ON(job) GROUP_RIGHT() sum(up) BY (job) != 1
|
||||||
|
for: 5m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: An unexpected number of Alertmanagers are scraped or Alertmanagers
|
||||||
|
disappeared from discovery.
|
||||||
|
- alert: AlertmanagerFailedReload
|
||||||
|
expr: alertmanager_config_last_reload_successful == 0
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Reloading Alertmanager's configuration has failed for {{ $labels.namespace
|
||||||
|
}}/{{ $labels.pod}}.
|
||||||
|
etcd3.rules.yaml: |+
|
||||||
|
groups:
|
||||||
|
- name: ./etcd3.rules
|
||||||
|
rules:
|
||||||
|
- alert: InsufficientMembers
|
||||||
|
expr: count(up{job="etcd"} == 0) > (count(up{job="etcd"}) / 2 - 1)
|
||||||
|
for: 3m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: If one more etcd member goes down the cluster will be unavailable
|
||||||
|
summary: etcd cluster insufficient members
|
||||||
|
- alert: NoLeader
|
||||||
|
expr: etcd_server_has_leader{job="etcd"} == 0
|
||||||
|
for: 1m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: etcd member {{ $labels.instance }} has no leader
|
||||||
|
summary: etcd member has no leader
|
||||||
|
- alert: HighNumberOfLeaderChanges
|
||||||
|
expr: increase(etcd_server_leader_changes_seen_total{job="etcd"}[1h]) > 3
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: etcd instance {{ $labels.instance }} has seen {{ $value }} leader
|
||||||
|
changes within the last hour
|
||||||
|
summary: a high number of leader changes within the etcd cluster are happening
|
||||||
|
- alert: HighNumberOfFailedGRPCRequests
|
||||||
|
expr: sum(rate(etcd_grpc_requests_failed_total{job="etcd"}[5m])) BY (grpc_method)
|
||||||
|
/ sum(rate(etcd_grpc_total{job="etcd"}[5m])) BY (grpc_method) > 0.01
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: '{{ $value }}% of requests for {{ $labels.grpc_method }} failed
|
||||||
|
on etcd instance {{ $labels.instance }}'
|
||||||
|
summary: a high number of gRPC requests are failing
|
||||||
|
- alert: HighNumberOfFailedGRPCRequests
|
||||||
|
expr: sum(rate(etcd_grpc_requests_failed_total{job="etcd"}[5m])) BY (grpc_method)
|
||||||
|
/ sum(rate(etcd_grpc_total{job="etcd"}[5m])) BY (grpc_method) > 0.05
|
||||||
|
for: 5m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: '{{ $value }}% of requests for {{ $labels.grpc_method }} failed
|
||||||
|
on etcd instance {{ $labels.instance }}'
|
||||||
|
summary: a high number of gRPC requests are failing
|
||||||
|
- alert: GRPCRequestsSlow
|
||||||
|
expr: histogram_quantile(0.99, rate(etcd_grpc_unary_requests_duration_seconds_bucket[5m]))
|
||||||
|
> 0.15
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: on etcd instance {{ $labels.instance }} gRPC requests to {{ $labels.grpc_method
|
||||||
|
}} are slow
|
||||||
|
summary: slow gRPC requests
|
||||||
|
- alert: HighNumberOfFailedHTTPRequests
|
||||||
|
expr: sum(rate(etcd_http_failed_total{job="etcd"}[5m])) BY (method) / sum(rate(etcd_http_received_total{job="etcd"}[5m]))
|
||||||
|
BY (method) > 0.01
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: '{{ $value }}% of requests for {{ $labels.method }} failed on etcd
|
||||||
|
instance {{ $labels.instance }}'
|
||||||
|
summary: a high number of HTTP requests are failing
|
||||||
|
- alert: HighNumberOfFailedHTTPRequests
|
||||||
|
expr: sum(rate(etcd_http_failed_total{job="etcd"}[5m])) BY (method) / sum(rate(etcd_http_received_total{job="etcd"}[5m]))
|
||||||
|
BY (method) > 0.05
|
||||||
|
for: 5m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: '{{ $value }}% of requests for {{ $labels.method }} failed on etcd
|
||||||
|
instance {{ $labels.instance }}'
|
||||||
|
summary: a high number of HTTP requests are failing
|
||||||
|
- alert: HTTPRequestsSlow
|
||||||
|
expr: histogram_quantile(0.99, rate(etcd_http_successful_duration_seconds_bucket[5m]))
|
||||||
|
> 0.15
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: on etcd instance {{ $labels.instance }} HTTP requests to {{ $labels.method
|
||||||
|
}} are slow
|
||||||
|
summary: slow HTTP requests
|
||||||
|
- alert: EtcdMemberCommunicationSlow
|
||||||
|
expr: histogram_quantile(0.99, rate(etcd_network_member_round_trip_time_seconds_bucket[5m]))
|
||||||
|
> 0.15
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: etcd instance {{ $labels.instance }} member communication with
|
||||||
|
{{ $labels.To }} is slow
|
||||||
|
summary: etcd member communication is slow
|
||||||
|
- alert: HighNumberOfFailedProposals
|
||||||
|
expr: increase(etcd_server_proposals_failed_total{job="etcd"}[1h]) > 5
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: etcd instance {{ $labels.instance }} has seen {{ $value }} proposal
|
||||||
|
failures within the last hour
|
||||||
|
summary: a high number of proposals within the etcd cluster are failing
|
||||||
|
- alert: HighFsyncDurations
|
||||||
|
expr: histogram_quantile(0.99, rate(etcd_disk_wal_fsync_duration_seconds_bucket[5m]))
|
||||||
|
> 0.5
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: etcd instance {{ $labels.instance }} fync durations are high
|
||||||
|
summary: high fsync durations
|
||||||
|
- alert: HighCommitDurations
|
||||||
|
expr: histogram_quantile(0.99, rate(etcd_disk_backend_commit_duration_seconds_bucket[5m]))
|
||||||
|
> 0.25
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: etcd instance {{ $labels.instance }} commit durations are high
|
||||||
|
summary: high commit durations
|
||||||
|
general.rules.yaml: |+
|
||||||
|
groups:
|
||||||
|
- name: general.rules
|
||||||
|
rules:
|
||||||
|
- alert: TargetDown
|
||||||
|
expr: 100 * (count(up == 0) BY (job) / count(up) BY (job)) > 10
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: '{{ $value }}% of {{ $labels.job }} targets are down.'
|
||||||
|
summary: Targets are down
|
||||||
|
- record: fd_utilization
|
||||||
|
expr: process_open_fds / process_max_fds
|
||||||
|
- alert: FdExhaustionClose
|
||||||
|
expr: predict_linear(fd_utilization[1h], 3600 * 4) > 1
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: '{{ $labels.job }}: {{ $labels.namespace }}/{{ $labels.pod }} instance
|
||||||
|
will exhaust in file/socket descriptors within the next 4 hours'
|
||||||
|
summary: file descriptors soon exhausted
|
||||||
|
- alert: FdExhaustionClose
|
||||||
|
expr: predict_linear(fd_utilization[10m], 3600) > 1
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: '{{ $labels.job }}: {{ $labels.namespace }}/{{ $labels.pod }} instance
|
||||||
|
will exhaust in file/socket descriptors within the next hour'
|
||||||
|
summary: file descriptors soon exhausted
|
||||||
|
kube-controller-manager.rules.yaml: |+
|
||||||
|
groups:
|
||||||
|
- name: kube-controller-manager.rules
|
||||||
|
rules:
|
||||||
|
- alert: K8SControllerManagerDown
|
||||||
|
expr: absent(up{kubernetes_name="kube-controller-manager"} == 1)
|
||||||
|
for: 5m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: There is no running K8S controller manager. Deployments and replication
|
||||||
|
controllers are not making progress.
|
||||||
|
summary: Controller manager is down
|
||||||
|
kube-scheduler.rules.yaml: |+
|
||||||
|
groups:
|
||||||
|
- name: kube-scheduler.rules
|
||||||
|
rules:
|
||||||
|
- record: cluster:scheduler_e2e_scheduling_latency_seconds:quantile
|
||||||
|
expr: histogram_quantile(0.99, sum(scheduler_e2e_scheduling_latency_microseconds_bucket)
|
||||||
|
BY (le, cluster)) / 1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.99"
|
||||||
|
- record: cluster:scheduler_e2e_scheduling_latency_seconds:quantile
|
||||||
|
expr: histogram_quantile(0.9, sum(scheduler_e2e_scheduling_latency_microseconds_bucket)
|
||||||
|
BY (le, cluster)) / 1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.9"
|
||||||
|
- record: cluster:scheduler_e2e_scheduling_latency_seconds:quantile
|
||||||
|
expr: histogram_quantile(0.5, sum(scheduler_e2e_scheduling_latency_microseconds_bucket)
|
||||||
|
BY (le, cluster)) / 1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.5"
|
||||||
|
- record: cluster:scheduler_scheduling_algorithm_latency_seconds:quantile
|
||||||
|
expr: histogram_quantile(0.99, sum(scheduler_scheduling_algorithm_latency_microseconds_bucket)
|
||||||
|
BY (le, cluster)) / 1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.99"
|
||||||
|
- record: cluster:scheduler_scheduling_algorithm_latency_seconds:quantile
|
||||||
|
expr: histogram_quantile(0.9, sum(scheduler_scheduling_algorithm_latency_microseconds_bucket)
|
||||||
|
BY (le, cluster)) / 1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.9"
|
||||||
|
- record: cluster:scheduler_scheduling_algorithm_latency_seconds:quantile
|
||||||
|
expr: histogram_quantile(0.5, sum(scheduler_scheduling_algorithm_latency_microseconds_bucket)
|
||||||
|
BY (le, cluster)) / 1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.5"
|
||||||
|
- record: cluster:scheduler_binding_latency_seconds:quantile
|
||||||
|
expr: histogram_quantile(0.99, sum(scheduler_binding_latency_microseconds_bucket)
|
||||||
|
BY (le, cluster)) / 1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.99"
|
||||||
|
- record: cluster:scheduler_binding_latency_seconds:quantile
|
||||||
|
expr: histogram_quantile(0.9, sum(scheduler_binding_latency_microseconds_bucket)
|
||||||
|
BY (le, cluster)) / 1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.9"
|
||||||
|
- record: cluster:scheduler_binding_latency_seconds:quantile
|
||||||
|
expr: histogram_quantile(0.5, sum(scheduler_binding_latency_microseconds_bucket)
|
||||||
|
BY (le, cluster)) / 1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.5"
|
||||||
|
- alert: K8SSchedulerDown
|
||||||
|
expr: absent(up{kubernetes_name="kube-scheduler"} == 1)
|
||||||
|
for: 5m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: There is no running K8S scheduler. New pods are not being assigned
|
||||||
|
to nodes.
|
||||||
|
summary: Scheduler is down
|
||||||
|
kube-state-metrics.rules.yaml: |+
|
||||||
|
groups:
|
||||||
|
- name: kube-state-metrics.rules
|
||||||
|
rules:
|
||||||
|
- alert: DeploymentGenerationMismatch
|
||||||
|
expr: kube_deployment_status_observed_generation != kube_deployment_metadata_generation
|
||||||
|
for: 15m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Observed deployment generation does not match expected one for
|
||||||
|
deployment {{$labels.namespaces}}{{$labels.deployment}}
|
||||||
|
- alert: DeploymentReplicasNotUpdated
|
||||||
|
expr: ((kube_deployment_status_replicas_updated != kube_deployment_spec_replicas)
|
||||||
|
or (kube_deployment_status_replicas_available != kube_deployment_spec_replicas))
|
||||||
|
unless (kube_deployment_spec_paused == 1)
|
||||||
|
for: 15m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Replicas are not updated and available for deployment {{$labels.namespaces}}/{{$labels.deployment}}
|
||||||
|
- alert: DaemonSetRolloutStuck
|
||||||
|
expr: kube_daemonset_status_current_number_ready / kube_daemonset_status_desired_number_scheduled
|
||||||
|
* 100 < 100
|
||||||
|
for: 15m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Only {{$value}}% of desired pods scheduled and ready for daemon
|
||||||
|
set {{$labels.namespaces}}/{{$labels.daemonset}}
|
||||||
|
- alert: K8SDaemonSetsNotScheduled
|
||||||
|
expr: kube_daemonset_status_desired_number_scheduled - kube_daemonset_status_current_number_scheduled
|
||||||
|
> 0
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: A number of daemonsets are not scheduled.
|
||||||
|
summary: Daemonsets are not scheduled correctly
|
||||||
|
- alert: DaemonSetsMissScheduled
|
||||||
|
expr: kube_daemonset_status_number_misscheduled > 0
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: A number of daemonsets are running where they are not supposed
|
||||||
|
to run.
|
||||||
|
summary: Daemonsets are not scheduled correctly
|
||||||
|
- alert: PodFrequentlyRestarting
|
||||||
|
expr: increase(kube_pod_container_status_restarts[1h]) > 5
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Pod {{$labels.namespaces}}/{{$labels.pod}} is was restarted {{$value}}
|
||||||
|
times within the last hour
|
||||||
|
kubelet.rules.yaml: |+
|
||||||
|
groups:
|
||||||
|
- name: kubelet.rules
|
||||||
|
rules:
|
||||||
|
- alert: K8SNodeNotReady
|
||||||
|
expr: kube_node_status_condition{condition="Ready",status="true"} == 0
|
||||||
|
for: 1h
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: The Kubelet on {{ $labels.node }} has not checked in with the API,
|
||||||
|
or has set itself to NotReady, for more than an hour
|
||||||
|
summary: Node status is NotReady
|
||||||
|
- alert: K8SManyNodesNotReady
|
||||||
|
expr: count(kube_node_status_condition{condition="Ready",status="true"} == 0)
|
||||||
|
> 1 and (count(kube_node_status_condition{condition="Ready",status="true"} ==
|
||||||
|
0) / count(kube_node_status_condition{condition="Ready",status="true"})) > 0.2
|
||||||
|
for: 1m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: '{{ $value }}% of Kubernetes nodes are not ready'
|
||||||
|
- alert: K8SKubeletDown
|
||||||
|
expr: count(up{job="kubernetes-nodes"} == 0) / count(up{job="kubernetes-nodes"}) * 100 > 3
|
||||||
|
for: 1h
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Prometheus failed to scrape {{ $value }}% of kubelets.
|
||||||
|
- alert: K8SKubeletDown
|
||||||
|
expr: (absent(up{job="kubernetes-nodes"} == 1) or count(up{job="kubernetes-nodes"} == 0) / count(up{job="kubernetes-nodes"}))
|
||||||
|
* 100 > 1
|
||||||
|
for: 1h
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: Prometheus failed to scrape {{ $value }}% of kubelets, or all Kubelets
|
||||||
|
have disappeared from service discovery.
|
||||||
|
summary: Many Kubelets cannot be scraped
|
||||||
|
- alert: K8SKubeletTooManyPods
|
||||||
|
expr: kubelet_running_pod_count > 100
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Kubelet {{$labels.instance}} is running {{$value}} pods, close
|
||||||
|
to the limit of 110
|
||||||
|
summary: Kubelet is close to pod limit
|
||||||
|
kubernetes.rules.yaml: |+
|
||||||
|
groups:
|
||||||
|
- name: kubernetes.rules
|
||||||
|
rules:
|
||||||
|
- record: pod_name:container_memory_usage_bytes:sum
|
||||||
|
expr: sum(container_memory_usage_bytes{container_name!="POD",pod_name!=""}) BY
|
||||||
|
(pod_name)
|
||||||
|
- record: pod_name:container_spec_cpu_shares:sum
|
||||||
|
expr: sum(container_spec_cpu_shares{container_name!="POD",pod_name!=""}) BY (pod_name)
|
||||||
|
- record: pod_name:container_cpu_usage:sum
|
||||||
|
expr: sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name!=""}[5m]))
|
||||||
|
BY (pod_name)
|
||||||
|
- record: pod_name:container_fs_usage_bytes:sum
|
||||||
|
expr: sum(container_fs_usage_bytes{container_name!="POD",pod_name!=""}) BY (pod_name)
|
||||||
|
- record: namespace:container_memory_usage_bytes:sum
|
||||||
|
expr: sum(container_memory_usage_bytes{container_name!=""}) BY (namespace)
|
||||||
|
- record: namespace:container_spec_cpu_shares:sum
|
||||||
|
expr: sum(container_spec_cpu_shares{container_name!=""}) BY (namespace)
|
||||||
|
- record: namespace:container_cpu_usage:sum
|
||||||
|
expr: sum(rate(container_cpu_usage_seconds_total{container_name!="POD"}[5m]))
|
||||||
|
BY (namespace)
|
||||||
|
- record: cluster:memory_usage:ratio
|
||||||
|
expr: sum(container_memory_usage_bytes{container_name!="POD",pod_name!=""}) BY
|
||||||
|
(cluster) / sum(machine_memory_bytes) BY (cluster)
|
||||||
|
- record: cluster:container_spec_cpu_shares:ratio
|
||||||
|
expr: sum(container_spec_cpu_shares{container_name!="POD",pod_name!=""}) / 1000
|
||||||
|
/ sum(machine_cpu_cores)
|
||||||
|
- record: cluster:container_cpu_usage:ratio
|
||||||
|
expr: sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name!=""}[5m]))
|
||||||
|
/ sum(machine_cpu_cores)
|
||||||
|
- record: apiserver_latency_seconds:quantile
|
||||||
|
expr: histogram_quantile(0.99, rate(apiserver_request_latencies_bucket[5m])) /
|
||||||
|
1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.99"
|
||||||
|
- record: apiserver_latency:quantile_seconds
|
||||||
|
expr: histogram_quantile(0.9, rate(apiserver_request_latencies_bucket[5m])) /
|
||||||
|
1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.9"
|
||||||
|
- record: apiserver_latency_seconds:quantile
|
||||||
|
expr: histogram_quantile(0.5, rate(apiserver_request_latencies_bucket[5m])) /
|
||||||
|
1e+06
|
||||||
|
labels:
|
||||||
|
quantile: "0.5"
|
||||||
|
- alert: APIServerLatencyHigh
|
||||||
|
expr: apiserver_latency_seconds:quantile{quantile="0.99",subresource!="log",verb!~"^(?:WATCH|WATCHLIST|PROXY|CONNECT)$"}
|
||||||
|
> 1
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: the API server has a 99th percentile latency of {{ $value }} seconds
|
||||||
|
for {{$labels.verb}} {{$labels.resource}}
|
||||||
|
- alert: APIServerLatencyHigh
|
||||||
|
expr: apiserver_latency_seconds:quantile{quantile="0.99",subresource!="log",verb!~"^(?:WATCH|WATCHLIST|PROXY|CONNECT)$"}
|
||||||
|
> 4
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: the API server has a 99th percentile latency of {{ $value }} seconds
|
||||||
|
for {{$labels.verb}} {{$labels.resource}}
|
||||||
|
- alert: APIServerErrorsHigh
|
||||||
|
expr: rate(apiserver_request_count{code=~"^(?:5..)$"}[5m]) / rate(apiserver_request_count[5m])
|
||||||
|
* 100 > 2
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: API server returns errors for {{ $value }}% of requests
|
||||||
|
- alert: APIServerErrorsHigh
|
||||||
|
expr: rate(apiserver_request_count{code=~"^(?:5..)$"}[5m]) / rate(apiserver_request_count[5m])
|
||||||
|
* 100 > 5
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: API server returns errors for {{ $value }}% of requests
|
||||||
|
- alert: K8SApiserverDown
|
||||||
|
expr: absent(up{job="kubernetes-apiservers"} == 1)
|
||||||
|
for: 20m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: No API servers are reachable or all have disappeared from service
|
||||||
|
discovery
|
||||||
|
node.rules.yaml: |+
|
||||||
|
groups:
|
||||||
|
- name: node.rules
|
||||||
|
rules:
|
||||||
|
- record: instance:node_cpu:rate:sum
|
||||||
|
expr: sum(rate(node_cpu{mode!="idle",mode!="iowait",mode!~"^(?:guest.*)$"}[3m]))
|
||||||
|
BY (instance)
|
||||||
|
- record: instance:node_filesystem_usage:sum
|
||||||
|
expr: sum((node_filesystem_size{mountpoint="/"} - node_filesystem_free{mountpoint="/"}))
|
||||||
|
BY (instance)
|
||||||
|
- record: instance:node_network_receive_bytes:rate:sum
|
||||||
|
expr: sum(rate(node_network_receive_bytes[3m])) BY (instance)
|
||||||
|
- record: instance:node_network_transmit_bytes:rate:sum
|
||||||
|
expr: sum(rate(node_network_transmit_bytes[3m])) BY (instance)
|
||||||
|
- record: instance:node_cpu:ratio
|
||||||
|
expr: sum(rate(node_cpu{mode!="idle"}[5m])) WITHOUT (cpu, mode) / ON(instance)
|
||||||
|
GROUP_LEFT() count(sum(node_cpu) BY (instance, cpu)) BY (instance)
|
||||||
|
- record: cluster:node_cpu:sum_rate5m
|
||||||
|
expr: sum(rate(node_cpu{mode!="idle"}[5m]))
|
||||||
|
- record: cluster:node_cpu:ratio
|
||||||
|
expr: cluster:node_cpu:rate5m / count(sum(node_cpu) BY (instance, cpu))
|
||||||
|
- alert: NodeExporterDown
|
||||||
|
expr: absent(up{kubernetes_name="node-exporter"} == 1)
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Prometheus could not scrape a node-exporter for more than 10m,
|
||||||
|
or node-exporters have disappeared from discovery
|
||||||
|
- alert: NodeDiskRunningFull
|
||||||
|
expr: predict_linear(node_filesystem_free[6h], 3600 * 24) < 0
|
||||||
|
for: 30m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: device {{$labels.device}} on node {{$labels.instance}} is running
|
||||||
|
full within the next 24 hours (mounted at {{$labels.mountpoint}})
|
||||||
|
- alert: NodeDiskRunningFull
|
||||||
|
expr: predict_linear(node_filesystem_free[30m], 3600 * 2) < 0
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: device {{$labels.device}} on node {{$labels.instance}} is running
|
||||||
|
full within the next 2 hours (mounted at {{$labels.mountpoint}})
|
||||||
|
prometheus.rules.yaml: |+
|
||||||
|
groups:
|
||||||
|
- name: prometheus.rules
|
||||||
|
rules:
|
||||||
|
- alert: PrometheusConfigReloadFailed
|
||||||
|
expr: prometheus_config_last_reload_successful == 0
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Reloading Prometheus' configuration has failed for {{$labels.namespace}}/{{$labels.pod}}
|
||||||
|
- alert: PrometheusNotificationQueueRunningFull
|
||||||
|
expr: predict_linear(prometheus_notifications_queue_length[5m], 60 * 30) > prometheus_notifications_queue_capacity
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Prometheus' alert notification queue is running full for {{$labels.namespace}}/{{
|
||||||
|
$labels.pod}}
|
||||||
|
- alert: PrometheusErrorSendingAlerts
|
||||||
|
expr: rate(prometheus_notifications_errors_total[5m]) / rate(prometheus_notifications_sent_total[5m])
|
||||||
|
> 0.01
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Errors while sending alerts from Prometheus {{$labels.namespace}}/{{
|
||||||
|
$labels.pod}} to Alertmanager {{$labels.Alertmanager}}
|
||||||
|
- alert: PrometheusErrorSendingAlerts
|
||||||
|
expr: rate(prometheus_notifications_errors_total[5m]) / rate(prometheus_notifications_sent_total[5m])
|
||||||
|
> 0.03
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
annotations:
|
||||||
|
description: Errors while sending alerts from Prometheus {{$labels.namespace}}/{{
|
||||||
|
$labels.pod}} to Alertmanager {{$labels.Alertmanager}}
|
||||||
|
- alert: PrometheusNotConnectedToAlertmanagers
|
||||||
|
expr: prometheus_notifications_alertmanagers_discovered < 1
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: warning
|
||||||
|
annotations:
|
||||||
|
description: Prometheus {{ $labels.namespace }}/{{ $labels.pod}} is not connected
|
||||||
|
to any Alertmanagers
|
15
addons/prometheus/service.yaml
Normal file
15
addons/prometheus/service.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: prometheus
|
||||||
|
namespace: monitoring
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
name: prometheus
|
||||||
|
phase: prod
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 9090
|
23
aws/container-linux/kubernetes/LICENSE
Normal file
23
aws/container-linux/kubernetes/LICENSE
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2017 Typhoon Authors
|
||||||
|
Copyright (c) 2017 Dalton Hubble
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
22
aws/container-linux/kubernetes/README.md
Normal file
22
aws/container-linux/kubernetes/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Typhoon <img align="right" src="https://storage.googleapis.com/poseidon/typhoon-logo.png">
|
||||||
|
|
||||||
|
Typhoon is a minimal and free Kubernetes distribution.
|
||||||
|
|
||||||
|
* Minimal, stable base Kubernetes distribution
|
||||||
|
* Declarative infrastructure and configuration
|
||||||
|
* Free (freedom and cost) and privacy-respecting
|
||||||
|
* Practical for labs, datacenters, and clouds
|
||||||
|
|
||||||
|
Typhoon distributes upstream Kubernetes, architectural conventions, and cluster addons, much like a GNU/Linux distribution provides the Linux kernel and userspace components.
|
||||||
|
|
||||||
|
## Features <a href="https://www.cncf.io/certification/software-conformance/"><img align="right" src="https://storage.googleapis.com/poseidon/certified-kubernetes.png"></a>
|
||||||
|
|
||||||
|
* Kubernetes v1.8.6 (upstream, via [kubernetes-incubator/bootkube](https://github.com/kubernetes-incubator/bootkube))
|
||||||
|
* Single or multi-master, workloads isolated on workers, [Calico](https://www.projectcalico.org/) or [flannel](https://github.com/coreos/flannel) networking
|
||||||
|
* On-cluster etcd with TLS, [RBAC](https://kubernetes.io/docs/admin/authorization/rbac/)-enabled, [network policy](https://kubernetes.io/docs/concepts/services-networking/network-policies/)
|
||||||
|
* Ready for Ingress, Dashboards, Metrics, and other optional [addons](https://typhoon.psdn.io/addons/overview/)
|
||||||
|
|
||||||
|
## Docs
|
||||||
|
|
||||||
|
Please see the [official docs](https://typhoon.psdn.io) and the AWS [tutorial](https://typhoon.psdn.io/aws/).
|
||||||
|
|
19
aws/container-linux/kubernetes/ami.tf
Normal file
19
aws/container-linux/kubernetes/ami.tf
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
data "aws_ami" "coreos" {
|
||||||
|
most_recent = true
|
||||||
|
owners = ["595879546273"]
|
||||||
|
|
||||||
|
filter {
|
||||||
|
name = "architecture"
|
||||||
|
values = ["x86_64"]
|
||||||
|
}
|
||||||
|
|
||||||
|
filter {
|
||||||
|
name = "virtualization-type"
|
||||||
|
values = ["hvm"]
|
||||||
|
}
|
||||||
|
|
||||||
|
filter {
|
||||||
|
name = "name"
|
||||||
|
values = ["CoreOS-${var.os_channel}-*"]
|
||||||
|
}
|
||||||
|
}
|
14
aws/container-linux/kubernetes/bootkube.tf
Normal file
14
aws/container-linux/kubernetes/bootkube.tf
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Self-hosted Kubernetes assets (kubeconfig, manifests)
|
||||||
|
module "bootkube" {
|
||||||
|
source = "git::https://github.com/poseidon/terraform-render-bootkube.git?ref=5072569bb7dff1c2f6bc6fb7b06ce0a41809971e"
|
||||||
|
|
||||||
|
cluster_name = "${var.cluster_name}"
|
||||||
|
api_servers = ["${format("%s.%s", var.cluster_name, var.dns_zone)}"]
|
||||||
|
etcd_servers = ["${aws_route53_record.etcds.*.fqdn}"]
|
||||||
|
asset_dir = "${var.asset_dir}"
|
||||||
|
networking = "${var.networking}"
|
||||||
|
network_mtu = "${var.network_mtu}"
|
||||||
|
pod_cidr = "${var.pod_cidr}"
|
||||||
|
service_cidr = "${var.service_cidr}"
|
||||||
|
cluster_domain_suffix = "${var.cluster_domain_suffix}"
|
||||||
|
}
|
@ -1,6 +1,29 @@
|
|||||||
---
|
---
|
||||||
systemd:
|
systemd:
|
||||||
units:
|
units:
|
||||||
|
- name: etcd-member.service
|
||||||
|
enable: true
|
||||||
|
dropins:
|
||||||
|
- name: 40-etcd-cluster.conf
|
||||||
|
contents: |
|
||||||
|
[Service]
|
||||||
|
Environment="ETCD_IMAGE_TAG=v3.2.0"
|
||||||
|
Environment="ETCD_NAME=${etcd_name}"
|
||||||
|
Environment="ETCD_ADVERTISE_CLIENT_URLS=https://${etcd_domain}:2379"
|
||||||
|
Environment="ETCD_INITIAL_ADVERTISE_PEER_URLS=https://${etcd_domain}:2380"
|
||||||
|
Environment="ETCD_LISTEN_CLIENT_URLS=https://0.0.0.0:2379"
|
||||||
|
Environment="ETCD_LISTEN_PEER_URLS=https://0.0.0.0:2380"
|
||||||
|
Environment="ETCD_INITIAL_CLUSTER=${etcd_initial_cluster}"
|
||||||
|
Environment="ETCD_STRICT_RECONFIG_CHECK=true"
|
||||||
|
Environment="ETCD_SSL_DIR=/etc/ssl/etcd"
|
||||||
|
Environment="ETCD_TRUSTED_CA_FILE=/etc/ssl/certs/etcd/server-ca.crt"
|
||||||
|
Environment="ETCD_CERT_FILE=/etc/ssl/certs/etcd/server.crt"
|
||||||
|
Environment="ETCD_KEY_FILE=/etc/ssl/certs/etcd/server.key"
|
||||||
|
Environment="ETCD_CLIENT_CERT_AUTH=true"
|
||||||
|
Environment="ETCD_PEER_TRUSTED_CA_FILE=/etc/ssl/certs/etcd/peer-ca.crt"
|
||||||
|
Environment="ETCD_PEER_CERT_FILE=/etc/ssl/certs/etcd/peer.crt"
|
||||||
|
Environment="ETCD_PEER_KEY_FILE=/etc/ssl/certs/etcd/peer.key"
|
||||||
|
Environment="ETCD_PEER_CLIENT_CERT_AUTH=true"
|
||||||
- name: docker.service
|
- name: docker.service
|
||||||
enable: true
|
enable: true
|
||||||
- name: locksmithd.service
|
- name: locksmithd.service
|
||||||
@ -18,43 +41,48 @@ systemd:
|
|||||||
ExecStart=/bin/sh -c 'while ! /usr/bin/grep '^[^#[:space:]]' /etc/resolv.conf > /dev/null; do sleep 1; done'
|
ExecStart=/bin/sh -c 'while ! /usr/bin/grep '^[^#[:space:]]' /etc/resolv.conf > /dev/null; do sleep 1; done'
|
||||||
[Install]
|
[Install]
|
||||||
RequiredBy=kubelet.service
|
RequiredBy=kubelet.service
|
||||||
|
RequiredBy=etcd-member.service
|
||||||
- name: kubelet.service
|
- name: kubelet.service
|
||||||
enable: true
|
enable: true
|
||||||
contents: |
|
contents: |
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Kubelet via Hyperkube ACI
|
Description=Kubelet via Hyperkube ACI
|
||||||
|
Wants=rpc-statd.service
|
||||||
[Service]
|
[Service]
|
||||||
EnvironmentFile=/etc/kubernetes/kubelet.env
|
EnvironmentFile=/etc/kubernetes/kubelet.env
|
||||||
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/run/kubelet-pod.uuid \
|
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/cache/kubelet-pod.uuid \
|
||||||
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
||||||
--mount volume=resolv,target=/etc/resolv.conf \
|
--mount volume=resolv,target=/etc/resolv.conf \
|
||||||
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
||||||
--mount volume=var-lib-cni,target=/var/lib/cni \
|
--mount volume=var-lib-cni,target=/var/lib/cni \
|
||||||
|
--volume opt-cni-bin,kind=host,source=/opt/cni/bin \
|
||||||
|
--mount volume=opt-cni-bin,target=/opt/cni/bin \
|
||||||
--volume var-log,kind=host,source=/var/log \
|
--volume var-log,kind=host,source=/var/log \
|
||||||
--mount volume=var-log,target=/var/log"
|
--mount volume=var-log,target=/var/log \
|
||||||
|
--insecure-options=image"
|
||||||
|
ExecStartPre=/bin/mkdir -p /opt/cni/bin
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
||||||
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
||||||
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
||||||
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/run/kubelet-pod.uuid
|
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
||||||
--kubeconfig=/etc/kubernetes/kubeconfig \
|
|
||||||
--require-kubeconfig \
|
|
||||||
--client-ca-file=/etc/kubernetes/ca.crt \
|
|
||||||
--anonymous-auth=false \
|
|
||||||
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
|
||||||
--network-plugin=cni \
|
|
||||||
--lock-file=/var/run/lock/kubelet.lock \
|
|
||||||
--exit-on-lock-contention \
|
|
||||||
--pod-manifest-path=/etc/kubernetes/manifests \
|
|
||||||
--allow-privileged \
|
--allow-privileged \
|
||||||
--node-labels=node-role.kubernetes.io/master \
|
--anonymous-auth=false \
|
||||||
--register-with-taints=node-role.kubernetes.io/master=:NoSchedule \
|
--client-ca-file=/etc/kubernetes/ca.crt \
|
||||||
--cluster_dns=${k8s_dns_service_ip} \
|
--cluster_dns=${k8s_dns_service_ip} \
|
||||||
--cluster_domain=cluster.local
|
--cluster_domain=${cluster_domain_suffix} \
|
||||||
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/run/kubelet-pod.uuid
|
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
||||||
|
--exit-on-lock-contention \
|
||||||
|
--kubeconfig=/etc/kubernetes/kubeconfig \
|
||||||
|
--lock-file=/var/run/lock/kubelet.lock \
|
||||||
|
--network-plugin=cni \
|
||||||
|
--node-labels=node-role.kubernetes.io/master \
|
||||||
|
--pod-manifest-path=/etc/kubernetes/manifests \
|
||||||
|
--register-with-taints=node-role.kubernetes.io/master=:NoSchedule
|
||||||
|
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=10
|
RestartSec=10
|
||||||
[Install]
|
[Install]
|
||||||
@ -100,8 +128,8 @@ storage:
|
|||||||
mode: 0644
|
mode: 0644
|
||||||
contents:
|
contents:
|
||||||
inline: |
|
inline: |
|
||||||
KUBELET_IMAGE_URL=quay.io/coreos/hyperkube
|
KUBELET_IMAGE_URL=docker://gcr.io/google_containers/hyperkube
|
||||||
KUBELET_IMAGE_TAG=v1.7.3_coreos.0
|
KUBELET_IMAGE_TAG=v1.8.6
|
||||||
- path: /etc/sysctl.d/max-user-watches.conf
|
- path: /etc/sysctl.d/max-user-watches.conf
|
||||||
filesystem: root
|
filesystem: root
|
||||||
contents:
|
contents:
|
||||||
@ -120,11 +148,9 @@ storage:
|
|||||||
# Wrapper for bootkube start
|
# Wrapper for bootkube start
|
||||||
set -e
|
set -e
|
||||||
# Move experimental manifests
|
# Move experimental manifests
|
||||||
[ -d /opt/bootkube/assets/manifests-* ] && mv /opt/bootkube/assets/manifests-*/* /opt/bootkube/assets/manifests && rm -rf /opt/bootkube/assets/manifests-*
|
[ -n "$(ls /opt/bootkube/assets/manifests-*/* 2>/dev/null)" ] && mv /opt/bootkube/assets/manifests-*/* /opt/bootkube/assets/manifests && rm -rf /opt/bootkube/assets/manifests-*
|
||||||
[ -d /opt/bootkube/assets/experimental/manifests ] && mv /opt/bootkube/assets/experimental/manifests/* /opt/bootkube/assets/manifests && rm -r /opt/bootkube/assets/experimental/manifests
|
|
||||||
[ -d /opt/bootkube/assets/experimental/bootstrap-manifests ] && mv /opt/bootkube/assets/experimental/bootstrap-manifests/* /opt/bootkube/assets/bootstrap-manifests && rm -r /opt/bootkube/assets/experimental/bootstrap-manifests
|
|
||||||
BOOTKUBE_ACI="$${BOOTKUBE_ACI:-quay.io/coreos/bootkube}"
|
BOOTKUBE_ACI="$${BOOTKUBE_ACI:-quay.io/coreos/bootkube}"
|
||||||
BOOTKUBE_VERSION="$${BOOTKUBE_VERSION:-v0.6.1}"
|
BOOTKUBE_VERSION="$${BOOTKUBE_VERSION:-v0.9.1}"
|
||||||
BOOTKUBE_ASSETS="$${BOOTKUBE_ASSETS:-/opt/bootkube/assets}"
|
BOOTKUBE_ASSETS="$${BOOTKUBE_ASSETS:-/opt/bootkube/assets}"
|
||||||
exec /usr/bin/rkt run \
|
exec /usr/bin/rkt run \
|
||||||
--trust-keys-from-https \
|
--trust-keys-from-https \
|
||||||
@ -141,4 +167,4 @@ passwd:
|
|||||||
users:
|
users:
|
||||||
- name: core
|
- name: core
|
||||||
ssh_authorized_keys:
|
ssh_authorized_keys:
|
||||||
- "${ssh_authorized_keys}"
|
- "${ssh_authorized_key}"
|
@ -23,37 +23,41 @@ systemd:
|
|||||||
contents: |
|
contents: |
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Kubelet via Hyperkube ACI
|
Description=Kubelet via Hyperkube ACI
|
||||||
|
Wants=rpc-statd.service
|
||||||
[Service]
|
[Service]
|
||||||
EnvironmentFile=/etc/kubernetes/kubelet.env
|
EnvironmentFile=/etc/kubernetes/kubelet.env
|
||||||
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/run/kubelet-pod.uuid \
|
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/cache/kubelet-pod.uuid \
|
||||||
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
||||||
--mount volume=resolv,target=/etc/resolv.conf \
|
--mount volume=resolv,target=/etc/resolv.conf \
|
||||||
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
||||||
--mount volume=var-lib-cni,target=/var/lib/cni \
|
--mount volume=var-lib-cni,target=/var/lib/cni \
|
||||||
|
--volume opt-cni-bin,kind=host,source=/opt/cni/bin \
|
||||||
|
--mount volume=opt-cni-bin,target=/opt/cni/bin \
|
||||||
--volume var-log,kind=host,source=/var/log \
|
--volume var-log,kind=host,source=/var/log \
|
||||||
--mount volume=var-log,target=/var/log"
|
--mount volume=var-log,target=/var/log \
|
||||||
|
--insecure-options=image"
|
||||||
|
ExecStartPre=/bin/mkdir -p /opt/cni/bin
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
||||||
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
||||||
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
||||||
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/run/kubelet-pod.uuid
|
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
||||||
--kubeconfig=/etc/kubernetes/kubeconfig \
|
|
||||||
--require-kubeconfig \
|
|
||||||
--client-ca-file=/etc/kubernetes/ca.crt \
|
|
||||||
--anonymous-auth=false \
|
|
||||||
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
|
||||||
--network-plugin=cni \
|
|
||||||
--lock-file=/var/run/lock/kubelet.lock \
|
|
||||||
--exit-on-lock-contention \
|
|
||||||
--pod-manifest-path=/etc/kubernetes/manifests \
|
|
||||||
--allow-privileged \
|
--allow-privileged \
|
||||||
--node-labels=node-role.kubernetes.io/node \
|
--anonymous-auth=false \
|
||||||
|
--client-ca-file=/etc/kubernetes/ca.crt \
|
||||||
--cluster_dns=${k8s_dns_service_ip} \
|
--cluster_dns=${k8s_dns_service_ip} \
|
||||||
--cluster_domain=cluster.local
|
--cluster_domain=${cluster_domain_suffix} \
|
||||||
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/run/kubelet-pod.uuid
|
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
||||||
|
--exit-on-lock-contention \
|
||||||
|
--kubeconfig=/etc/kubernetes/kubeconfig \
|
||||||
|
--lock-file=/var/run/lock/kubelet.lock \
|
||||||
|
--network-plugin=cni \
|
||||||
|
--node-labels=node-role.kubernetes.io/node \
|
||||||
|
--pod-manifest-path=/etc/kubernetes/manifests
|
||||||
|
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
[Install]
|
[Install]
|
||||||
@ -98,8 +102,8 @@ storage:
|
|||||||
mode: 0644
|
mode: 0644
|
||||||
contents:
|
contents:
|
||||||
inline: |
|
inline: |
|
||||||
KUBELET_IMAGE_URL=quay.io/coreos/hyperkube
|
KUBELET_IMAGE_URL=docker://gcr.io/google_containers/hyperkube
|
||||||
KUBELET_IMAGE_TAG=v1.7.3_coreos.0
|
KUBELET_IMAGE_TAG=v1.8.6
|
||||||
- path: /etc/sysctl.d/max-user-watches.conf
|
- path: /etc/sysctl.d/max-user-watches.conf
|
||||||
filesystem: root
|
filesystem: root
|
||||||
contents:
|
contents:
|
||||||
@ -116,7 +120,8 @@ storage:
|
|||||||
--trust-keys-from-https \
|
--trust-keys-from-https \
|
||||||
--volume config,kind=host,source=/etc/kubernetes \
|
--volume config,kind=host,source=/etc/kubernetes \
|
||||||
--mount volume=config,target=/etc/kubernetes \
|
--mount volume=config,target=/etc/kubernetes \
|
||||||
quay.io/coreos/hyperkube:v1.7.3_coreos.0 \
|
--insecure-options=image \
|
||||||
|
docker://gcr.io/google_containers/hyperkube:v1.8.6 \
|
||||||
--net=host \
|
--net=host \
|
||||||
--dns=host \
|
--dns=host \
|
||||||
--exec=/kubectl -- --kubeconfig=/etc/kubernetes/kubeconfig delete node $(hostname)
|
--exec=/kubectl -- --kubeconfig=/etc/kubernetes/kubeconfig delete node $(hostname)
|
262
aws/container-linux/kubernetes/controllers.tf
Normal file
262
aws/container-linux/kubernetes/controllers.tf
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
# Discrete DNS records for each controller's private IPv4 for etcd usage
|
||||||
|
resource "aws_route53_record" "etcds" {
|
||||||
|
count = "${var.controller_count}"
|
||||||
|
|
||||||
|
# DNS Zone where record should be created
|
||||||
|
zone_id = "${var.dns_zone_id}"
|
||||||
|
|
||||||
|
name = "${format("%s-etcd%d.%s.", var.cluster_name, count.index, var.dns_zone)}"
|
||||||
|
type = "A"
|
||||||
|
ttl = 300
|
||||||
|
|
||||||
|
# private IPv4 address for etcd
|
||||||
|
records = ["${element(aws_instance.controllers.*.private_ip, count.index)}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Controller instances
|
||||||
|
resource "aws_instance" "controllers" {
|
||||||
|
count = "${var.controller_count}"
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.cluster_name}-controller-${count.index}"
|
||||||
|
}
|
||||||
|
|
||||||
|
instance_type = "${var.controller_type}"
|
||||||
|
|
||||||
|
ami = "${data.aws_ami.coreos.image_id}"
|
||||||
|
user_data = "${element(data.ct_config.controller_ign.*.rendered, count.index)}"
|
||||||
|
|
||||||
|
# storage
|
||||||
|
root_block_device {
|
||||||
|
volume_type = "standard"
|
||||||
|
volume_size = "${var.disk_size}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# network
|
||||||
|
associate_public_ip_address = true
|
||||||
|
subnet_id = "${element(aws_subnet.public.*.id, count.index)}"
|
||||||
|
vpc_security_group_ids = ["${aws_security_group.controller.id}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Controller Container Linux Config
|
||||||
|
data "template_file" "controller_config" {
|
||||||
|
count = "${var.controller_count}"
|
||||||
|
|
||||||
|
template = "${file("${path.module}/cl/controller.yaml.tmpl")}"
|
||||||
|
|
||||||
|
vars = {
|
||||||
|
# Cannot use cyclic dependencies on controllers or their DNS records
|
||||||
|
etcd_name = "etcd${count.index}"
|
||||||
|
etcd_domain = "${var.cluster_name}-etcd${count.index}.${var.dns_zone}"
|
||||||
|
|
||||||
|
# etcd0=https://cluster-etcd0.example.com,etcd1=https://cluster-etcd1.example.com,...
|
||||||
|
etcd_initial_cluster = "${join(",", formatlist("%s=https://%s:2380", null_resource.repeat.*.triggers.name, null_resource.repeat.*.triggers.domain))}"
|
||||||
|
|
||||||
|
k8s_dns_service_ip = "${cidrhost(var.service_cidr, 10)}"
|
||||||
|
ssh_authorized_key = "${var.ssh_authorized_key}"
|
||||||
|
cluster_domain_suffix = "${var.cluster_domain_suffix}"
|
||||||
|
kubeconfig_ca_cert = "${module.bootkube.ca_cert}"
|
||||||
|
kubeconfig_kubelet_cert = "${module.bootkube.kubelet_cert}"
|
||||||
|
kubeconfig_kubelet_key = "${module.bootkube.kubelet_key}"
|
||||||
|
kubeconfig_server = "${module.bootkube.server}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Horrible hack to generate a Terraform list of a desired length without dependencies.
|
||||||
|
# Ideal ${repeat("etcd", 3) -> ["etcd", "etcd", "etcd"]}
|
||||||
|
resource null_resource "repeat" {
|
||||||
|
count = "${var.controller_count}"
|
||||||
|
|
||||||
|
triggers {
|
||||||
|
name = "etcd${count.index}"
|
||||||
|
domain = "${var.cluster_name}-etcd${count.index}.${var.dns_zone}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "ct_config" "controller_ign" {
|
||||||
|
count = "${var.controller_count}"
|
||||||
|
content = "${element(data.template_file.controller_config.*.rendered, count.index)}"
|
||||||
|
pretty_print = false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security Group (instance firewall)
|
||||||
|
|
||||||
|
resource "aws_security_group" "controller" {
|
||||||
|
name = "${var.cluster_name}-controller"
|
||||||
|
description = "${var.cluster_name} controller security group"
|
||||||
|
|
||||||
|
vpc_id = "${aws_vpc.network.id}"
|
||||||
|
|
||||||
|
tags = "${map("Name", "${var.cluster_name}-controller")}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-icmp" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "icmp"
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
cidr_blocks = ["0.0.0.0/0"]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-ssh" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 22
|
||||||
|
to_port = 22
|
||||||
|
cidr_blocks = ["0.0.0.0/0"]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-apiserver" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 443
|
||||||
|
to_port = 443
|
||||||
|
cidr_blocks = ["0.0.0.0/0"]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-etcd" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 2379
|
||||||
|
to_port = 2380
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-flannel" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "udp"
|
||||||
|
from_port = 8472
|
||||||
|
to_port = 8472
|
||||||
|
source_security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-flannel-self" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "udp"
|
||||||
|
from_port = 8472
|
||||||
|
to_port = 8472
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-node-exporter" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 9100
|
||||||
|
to_port = 9100
|
||||||
|
source_security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-kubelet-self" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 10250
|
||||||
|
to_port = 10250
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-kubelet-read" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 10255
|
||||||
|
to_port = 10255
|
||||||
|
source_security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-kubelet-read-self" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 10255
|
||||||
|
to_port = 10255
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-bgp" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 179
|
||||||
|
to_port = 179
|
||||||
|
source_security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-bgp-self" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 179
|
||||||
|
to_port = 179
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-ipip" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = 4
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
source_security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-ipip-self" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = 4
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-ipip-legacy" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = 94
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
source_security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-ipip-legacy-self" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = 94
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "controller-egress" {
|
||||||
|
security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
|
||||||
|
type = "egress"
|
||||||
|
protocol = "-1"
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
cidr_blocks = ["0.0.0.0/0"]
|
||||||
|
ipv6_cidr_blocks = ["::/0"]
|
||||||
|
}
|
43
aws/container-linux/kubernetes/elb.tf
Normal file
43
aws/container-linux/kubernetes/elb.tf
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# kube-apiserver Network Load Balancer DNS Record
|
||||||
|
resource "aws_route53_record" "apiserver" {
|
||||||
|
zone_id = "${var.dns_zone_id}"
|
||||||
|
|
||||||
|
name = "${format("%s.%s.", var.cluster_name, var.dns_zone)}"
|
||||||
|
type = "A"
|
||||||
|
|
||||||
|
# AWS recommends their special "alias" records for ELBs
|
||||||
|
alias {
|
||||||
|
name = "${aws_elb.apiserver.dns_name}"
|
||||||
|
zone_id = "${aws_elb.apiserver.zone_id}"
|
||||||
|
evaluate_target_health = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Controller Network Load Balancer
|
||||||
|
resource "aws_elb" "apiserver" {
|
||||||
|
name = "${var.cluster_name}-apiserver"
|
||||||
|
subnets = ["${aws_subnet.public.*.id}"]
|
||||||
|
security_groups = ["${aws_security_group.controller.id}"]
|
||||||
|
|
||||||
|
listener {
|
||||||
|
lb_port = 443
|
||||||
|
lb_protocol = "tcp"
|
||||||
|
instance_port = 443
|
||||||
|
instance_protocol = "tcp"
|
||||||
|
}
|
||||||
|
|
||||||
|
instances = ["${aws_instance.controllers.*.id}"]
|
||||||
|
|
||||||
|
# Kubelet HTTP health check
|
||||||
|
health_check {
|
||||||
|
target = "SSL:443"
|
||||||
|
healthy_threshold = 2
|
||||||
|
unhealthy_threshold = 4
|
||||||
|
timeout = 5
|
||||||
|
interval = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
idle_timeout = 3600
|
||||||
|
connection_draining = true
|
||||||
|
connection_draining_timeout = 300
|
||||||
|
}
|
32
aws/container-linux/kubernetes/ingress.tf
Normal file
32
aws/container-linux/kubernetes/ingress.tf
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Ingress Network Load Balancer
|
||||||
|
resource "aws_elb" "ingress" {
|
||||||
|
name = "${var.cluster_name}-ingress"
|
||||||
|
subnets = ["${aws_subnet.public.*.id}"]
|
||||||
|
security_groups = ["${aws_security_group.worker.id}"]
|
||||||
|
|
||||||
|
listener {
|
||||||
|
lb_port = 80
|
||||||
|
lb_protocol = "tcp"
|
||||||
|
instance_port = 80
|
||||||
|
instance_protocol = "tcp"
|
||||||
|
}
|
||||||
|
|
||||||
|
listener {
|
||||||
|
lb_port = 443
|
||||||
|
lb_protocol = "tcp"
|
||||||
|
instance_port = 443
|
||||||
|
instance_protocol = "tcp"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ingress Controller HTTP health check
|
||||||
|
health_check {
|
||||||
|
target = "HTTP:10254/healthz"
|
||||||
|
healthy_threshold = 2
|
||||||
|
unhealthy_threshold = 4
|
||||||
|
timeout = 5
|
||||||
|
interval = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
connection_draining = true
|
||||||
|
connection_draining_timeout = 300
|
||||||
|
}
|
57
aws/container-linux/kubernetes/network.tf
Normal file
57
aws/container-linux/kubernetes/network.tf
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
data "aws_availability_zones" "all" {}
|
||||||
|
|
||||||
|
# Network VPC, gateway, and routes
|
||||||
|
|
||||||
|
resource "aws_vpc" "network" {
|
||||||
|
cidr_block = "${var.host_cidr}"
|
||||||
|
assign_generated_ipv6_cidr_block = true
|
||||||
|
enable_dns_support = true
|
||||||
|
enable_dns_hostnames = true
|
||||||
|
|
||||||
|
tags = "${map("Name", "${var.cluster_name}")}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_internet_gateway" "gateway" {
|
||||||
|
vpc_id = "${aws_vpc.network.id}"
|
||||||
|
|
||||||
|
tags = "${map("Name", "${var.cluster_name}")}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_route_table" "default" {
|
||||||
|
vpc_id = "${aws_vpc.network.id}"
|
||||||
|
|
||||||
|
route {
|
||||||
|
cidr_block = "0.0.0.0/0"
|
||||||
|
gateway_id = "${aws_internet_gateway.gateway.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
route {
|
||||||
|
ipv6_cidr_block = "::/0"
|
||||||
|
gateway_id = "${aws_internet_gateway.gateway.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = "${map("Name", "${var.cluster_name}")}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Subnets (one per availability zone)
|
||||||
|
|
||||||
|
resource "aws_subnet" "public" {
|
||||||
|
count = "${length(data.aws_availability_zones.all.names)}"
|
||||||
|
|
||||||
|
vpc_id = "${aws_vpc.network.id}"
|
||||||
|
availability_zone = "${data.aws_availability_zones.all.names[count.index]}"
|
||||||
|
|
||||||
|
cidr_block = "${cidrsubnet(var.host_cidr, 4, count.index)}"
|
||||||
|
ipv6_cidr_block = "${cidrsubnet(aws_vpc.network.ipv6_cidr_block, 8, count.index)}"
|
||||||
|
map_public_ip_on_launch = true
|
||||||
|
assign_ipv6_address_on_creation = true
|
||||||
|
|
||||||
|
tags = "${map("Name", "${var.cluster_name}-public-${count.index}")}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_route_table_association" "public" {
|
||||||
|
count = "${length(data.aws_availability_zones.all.names)}"
|
||||||
|
|
||||||
|
route_table_id = "${aws_route_table.default.id}"
|
||||||
|
subnet_id = "${element(aws_subnet.public.*.id, count.index)}"
|
||||||
|
}
|
4
aws/container-linux/kubernetes/outputs.tf
Normal file
4
aws/container-linux/kubernetes/outputs.tf
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
output "ingress_dns_name" {
|
||||||
|
value = "${aws_elb.ingress.dns_name}"
|
||||||
|
description = "DNS name of the ELB for distributing traffic to Ingress controllers"
|
||||||
|
}
|
25
aws/container-linux/kubernetes/require.tf
Normal file
25
aws/container-linux/kubernetes/require.tf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Terraform version and plugin versions
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.10.4"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "aws" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "local" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "null" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "template" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "tls" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
92
aws/container-linux/kubernetes/ssh.tf
Normal file
92
aws/container-linux/kubernetes/ssh.tf
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
# Secure copy etcd TLS assets and kubeconfig to controllers. Activates kubelet.service
|
||||||
|
resource "null_resource" "copy-secrets" {
|
||||||
|
count = "${var.controller_count}"
|
||||||
|
|
||||||
|
connection {
|
||||||
|
type = "ssh"
|
||||||
|
host = "${element(aws_instance.controllers.*.public_ip, count.index)}"
|
||||||
|
user = "core"
|
||||||
|
timeout = "15m"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.kubeconfig}"
|
||||||
|
destination = "$HOME/kubeconfig"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_ca_cert}"
|
||||||
|
destination = "$HOME/etcd-client-ca.crt"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_client_cert}"
|
||||||
|
destination = "$HOME/etcd-client.crt"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_client_key}"
|
||||||
|
destination = "$HOME/etcd-client.key"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_server_cert}"
|
||||||
|
destination = "$HOME/etcd-server.crt"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_server_key}"
|
||||||
|
destination = "$HOME/etcd-server.key"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_peer_cert}"
|
||||||
|
destination = "$HOME/etcd-peer.crt"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_peer_key}"
|
||||||
|
destination = "$HOME/etcd-peer.key"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
inline = [
|
||||||
|
"sudo mkdir -p /etc/ssl/etcd/etcd",
|
||||||
|
"sudo mv etcd-client* /etc/ssl/etcd/",
|
||||||
|
"sudo cp /etc/ssl/etcd/etcd-client-ca.crt /etc/ssl/etcd/etcd/server-ca.crt",
|
||||||
|
"sudo mv etcd-server.crt /etc/ssl/etcd/etcd/server.crt",
|
||||||
|
"sudo mv etcd-server.key /etc/ssl/etcd/etcd/server.key",
|
||||||
|
"sudo cp /etc/ssl/etcd/etcd-client-ca.crt /etc/ssl/etcd/etcd/peer-ca.crt",
|
||||||
|
"sudo mv etcd-peer.crt /etc/ssl/etcd/etcd/peer.crt",
|
||||||
|
"sudo mv etcd-peer.key /etc/ssl/etcd/etcd/peer.key",
|
||||||
|
"sudo chown -R etcd:etcd /etc/ssl/etcd",
|
||||||
|
"sudo chmod -R 500 /etc/ssl/etcd",
|
||||||
|
"sudo mv /home/core/kubeconfig /etc/kubernetes/kubeconfig",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Secure copy bootkube assets to ONE controller and start bootkube to perform
|
||||||
|
# one-time self-hosted cluster bootstrapping.
|
||||||
|
resource "null_resource" "bootkube-start" {
|
||||||
|
depends_on = ["module.bootkube", "null_resource.copy-secrets", "aws_route53_record.apiserver"]
|
||||||
|
|
||||||
|
connection {
|
||||||
|
type = "ssh"
|
||||||
|
host = "${aws_instance.controllers.0.public_ip}"
|
||||||
|
user = "core"
|
||||||
|
timeout = "15m"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
source = "${var.asset_dir}"
|
||||||
|
destination = "$HOME/assets"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
inline = [
|
||||||
|
"sudo mv /home/core/assets /opt/bootkube",
|
||||||
|
"sudo systemctl start bootkube",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
102
aws/container-linux/kubernetes/variables.tf
Normal file
102
aws/container-linux/kubernetes/variables.tf
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
variable "cluster_name" {
|
||||||
|
type = "string"
|
||||||
|
description = "Cluster name"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "dns_zone" {
|
||||||
|
type = "string"
|
||||||
|
description = "AWS DNS Zone (e.g. aws.dghubble.io)"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "dns_zone_id" {
|
||||||
|
type = "string"
|
||||||
|
description = "AWS DNS Zone ID (e.g. Z3PAABBCFAKEC0)"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_authorized_key" {
|
||||||
|
type = "string"
|
||||||
|
description = "SSH public key for user 'core'"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "os_channel" {
|
||||||
|
type = "string"
|
||||||
|
default = "stable"
|
||||||
|
description = "Container Linux AMI channel (stable, beta, alpha)"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "disk_size" {
|
||||||
|
type = "string"
|
||||||
|
default = "40"
|
||||||
|
description = "The size of the disk in Gigabytes"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "host_cidr" {
|
||||||
|
description = "CIDR IPv4 range to assign to EC2 nodes"
|
||||||
|
type = "string"
|
||||||
|
default = "10.0.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "controller_count" {
|
||||||
|
type = "string"
|
||||||
|
default = "1"
|
||||||
|
description = "Number of controllers"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "controller_type" {
|
||||||
|
type = "string"
|
||||||
|
default = "t2.small"
|
||||||
|
description = "Controller EC2 instance type"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "worker_count" {
|
||||||
|
type = "string"
|
||||||
|
default = "1"
|
||||||
|
description = "Number of workers"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "worker_type" {
|
||||||
|
type = "string"
|
||||||
|
default = "t2.small"
|
||||||
|
description = "Worker EC2 instance type"
|
||||||
|
}
|
||||||
|
|
||||||
|
# bootkube assets
|
||||||
|
|
||||||
|
variable "asset_dir" {
|
||||||
|
description = "Path to a directory where generated assets should be placed (contains secrets)"
|
||||||
|
type = "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "networking" {
|
||||||
|
description = "Choice of networking provider (calico or flannel)"
|
||||||
|
type = "string"
|
||||||
|
default = "calico"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "network_mtu" {
|
||||||
|
description = "CNI interface MTU (applies to calico only). Use 8981 if using instances types with Jumbo frames."
|
||||||
|
type = "string"
|
||||||
|
default = "1480"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "pod_cidr" {
|
||||||
|
description = "CIDR IPv4 range to assign Kubernetes pods"
|
||||||
|
type = "string"
|
||||||
|
default = "10.2.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "service_cidr" {
|
||||||
|
description = <<EOD
|
||||||
|
CIDR IPv4 range to assign Kubernetes services.
|
||||||
|
The 1st IP will be reserved for kube_apiserver, the 10th IP will be reserved for kube-dns.
|
||||||
|
EOD
|
||||||
|
|
||||||
|
type = "string"
|
||||||
|
default = "10.3.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "cluster_domain_suffix" {
|
||||||
|
description = "Queries for domains with the suffix will be answered by kube-dns. Default is cluster.local (e.g. foo.default.svc.cluster.local) "
|
||||||
|
type = "string"
|
||||||
|
default = "cluster.local"
|
||||||
|
}
|
275
aws/container-linux/kubernetes/workers.tf
Normal file
275
aws/container-linux/kubernetes/workers.tf
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
# Workers AutoScaling Group
|
||||||
|
resource "aws_autoscaling_group" "workers" {
|
||||||
|
name = "${var.cluster_name}-worker ${aws_launch_configuration.worker.name}"
|
||||||
|
load_balancers = ["${aws_elb.ingress.id}"]
|
||||||
|
|
||||||
|
# count
|
||||||
|
desired_capacity = "${var.worker_count}"
|
||||||
|
min_size = "${var.worker_count}"
|
||||||
|
max_size = "${var.worker_count + 2}"
|
||||||
|
default_cooldown = 30
|
||||||
|
health_check_grace_period = 30
|
||||||
|
|
||||||
|
# network
|
||||||
|
vpc_zone_identifier = ["${aws_subnet.public.*.id}"]
|
||||||
|
|
||||||
|
# template
|
||||||
|
launch_configuration = "${aws_launch_configuration.worker.name}"
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
# override the default destroy and replace update behavior
|
||||||
|
create_before_destroy = true
|
||||||
|
ignore_changes = ["image_id"]
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = [{
|
||||||
|
key = "Name"
|
||||||
|
value = "${var.cluster_name}-worker"
|
||||||
|
propagate_at_launch = true
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Worker template
|
||||||
|
resource "aws_launch_configuration" "worker" {
|
||||||
|
image_id = "${data.aws_ami.coreos.image_id}"
|
||||||
|
instance_type = "${var.worker_type}"
|
||||||
|
|
||||||
|
user_data = "${data.ct_config.worker_ign.rendered}"
|
||||||
|
|
||||||
|
# storage
|
||||||
|
root_block_device {
|
||||||
|
volume_type = "standard"
|
||||||
|
volume_size = "${var.disk_size}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# network
|
||||||
|
security_groups = ["${aws_security_group.worker.id}"]
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
// Override the default destroy and replace update behavior
|
||||||
|
create_before_destroy = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Worker Container Linux Config
|
||||||
|
data "template_file" "worker_config" {
|
||||||
|
template = "${file("${path.module}/cl/worker.yaml.tmpl")}"
|
||||||
|
|
||||||
|
vars = {
|
||||||
|
k8s_dns_service_ip = "${cidrhost(var.service_cidr, 10)}"
|
||||||
|
k8s_etcd_service_ip = "${cidrhost(var.service_cidr, 15)}"
|
||||||
|
ssh_authorized_key = "${var.ssh_authorized_key}"
|
||||||
|
cluster_domain_suffix = "${var.cluster_domain_suffix}"
|
||||||
|
kubeconfig_ca_cert = "${module.bootkube.ca_cert}"
|
||||||
|
kubeconfig_kubelet_cert = "${module.bootkube.kubelet_cert}"
|
||||||
|
kubeconfig_kubelet_key = "${module.bootkube.kubelet_key}"
|
||||||
|
kubeconfig_server = "${module.bootkube.server}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "ct_config" "worker_ign" {
|
||||||
|
content = "${data.template_file.worker_config.rendered}"
|
||||||
|
pretty_print = false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security Group (instance firewall)
|
||||||
|
|
||||||
|
resource "aws_security_group" "worker" {
|
||||||
|
name = "${var.cluster_name}-worker"
|
||||||
|
description = "${var.cluster_name} worker security group"
|
||||||
|
|
||||||
|
vpc_id = "${aws_vpc.network.id}"
|
||||||
|
|
||||||
|
tags = "${map("Name", "${var.cluster_name}-worker")}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-icmp" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "icmp"
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
cidr_blocks = ["0.0.0.0/0"]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-ssh" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 22
|
||||||
|
to_port = 22
|
||||||
|
cidr_blocks = ["0.0.0.0/0"]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-http" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 80
|
||||||
|
to_port = 80
|
||||||
|
cidr_blocks = ["0.0.0.0/0"]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-https" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 443
|
||||||
|
to_port = 443
|
||||||
|
cidr_blocks = ["0.0.0.0/0"]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-flannel" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "udp"
|
||||||
|
from_port = 8472
|
||||||
|
to_port = 8472
|
||||||
|
source_security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-flannel-self" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "udp"
|
||||||
|
from_port = 8472
|
||||||
|
to_port = 8472
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-node-exporter" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 9100
|
||||||
|
to_port = 9100
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-kubelet" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 10250
|
||||||
|
to_port = 10250
|
||||||
|
source_security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-kubelet-self" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 10250
|
||||||
|
to_port = 10250
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-kubelet-read" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 10255
|
||||||
|
to_port = 10255
|
||||||
|
source_security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-kubelet-read-self" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 10255
|
||||||
|
to_port = 10255
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "ingress-health-self" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 10254
|
||||||
|
to_port = 10254
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-bgp" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 179
|
||||||
|
to_port = 179
|
||||||
|
source_security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-bgp-self" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = "tcp"
|
||||||
|
from_port = 179
|
||||||
|
to_port = 179
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-ipip" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = 4
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
source_security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-ipip-self" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = 4
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-ipip-legacy" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = 94
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
source_security_group_id = "${aws_security_group.controller.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-ipip-legacy-self" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "ingress"
|
||||||
|
protocol = 94
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
self = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_security_group_rule" "worker-egress" {
|
||||||
|
security_group_id = "${aws_security_group.worker.id}"
|
||||||
|
|
||||||
|
type = "egress"
|
||||||
|
protocol = "-1"
|
||||||
|
from_port = 0
|
||||||
|
to_port = 0
|
||||||
|
cidr_blocks = ["0.0.0.0/0"]
|
||||||
|
ipv6_cidr_blocks = ["::/0"]
|
||||||
|
}
|
23
bare-metal/container-linux/kubernetes/LICENSE
Normal file
23
bare-metal/container-linux/kubernetes/LICENSE
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2017 Typhoon Authors
|
||||||
|
Copyright (c) 2017 Dalton Hubble
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
22
bare-metal/container-linux/kubernetes/README.md
Normal file
22
bare-metal/container-linux/kubernetes/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Typhoon <img align="right" src="https://storage.googleapis.com/poseidon/typhoon-logo.png">
|
||||||
|
|
||||||
|
Typhoon is a minimal and free Kubernetes distribution.
|
||||||
|
|
||||||
|
* Minimal, stable base Kubernetes distribution
|
||||||
|
* Declarative infrastructure and configuration
|
||||||
|
* Free (freedom and cost) and privacy-respecting
|
||||||
|
* Practical for labs, datacenters, and clouds
|
||||||
|
|
||||||
|
Typhoon distributes upstream Kubernetes, architectural conventions, and cluster addons, much like a GNU/Linux distribution provides the Linux kernel and userspace components.
|
||||||
|
|
||||||
|
## Features <a href="https://www.cncf.io/certification/software-conformance/"><img align="right" src="https://storage.googleapis.com/poseidon/certified-kubernetes.png"></a>
|
||||||
|
|
||||||
|
* Kubernetes v1.8.6 (upstream, via [kubernetes-incubator/bootkube](https://github.com/kubernetes-incubator/bootkube))
|
||||||
|
* Single or multi-master, workloads isolated on workers, [Calico](https://www.projectcalico.org/) or [flannel](https://github.com/coreos/flannel) networking
|
||||||
|
* On-cluster etcd with TLS, [RBAC](https://kubernetes.io/docs/admin/authorization/rbac/)-enabled, [network policy](https://kubernetes.io/docs/concepts/services-networking/network-policies/)
|
||||||
|
* Ready for Ingress, Dashboards, Metrics, and other optional [addons](https://typhoon.psdn.io/addons/overview/)
|
||||||
|
|
||||||
|
## Docs
|
||||||
|
|
||||||
|
Please see the [official docs](https://typhoon.psdn.io) and the bare-metal [tutorial](https://typhoon.psdn.io/bare-metal/).
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
# Self-hosted Kubernetes assets (kubeconfig, manifests)
|
# Self-hosted Kubernetes assets (kubeconfig, manifests)
|
||||||
module "bootkube" {
|
module "bootkube" {
|
||||||
source = "git::https://github.com/poseidon/bootkube-terraform.git?ref=5ffbfec46dc05721eaf9d15c3c9bbedefaead1bc"
|
source = "git::https://github.com/poseidon/terraform-render-bootkube.git?ref=5072569bb7dff1c2f6bc6fb7b06ce0a41809971e"
|
||||||
|
|
||||||
cluster_name = "${var.cluster_name}"
|
cluster_name = "${var.cluster_name}"
|
||||||
api_servers = ["${var.k8s_domain_name}"]
|
api_servers = ["${var.k8s_domain_name}"]
|
||||||
@ -10,5 +10,5 @@ module "bootkube" {
|
|||||||
network_mtu = "${var.network_mtu}"
|
network_mtu = "${var.network_mtu}"
|
||||||
pod_cidr = "${var.pod_cidr}"
|
pod_cidr = "${var.pod_cidr}"
|
||||||
service_cidr = "${var.service_cidr}"
|
service_cidr = "${var.service_cidr}"
|
||||||
experimental_self_hosted_etcd = "${var.experimental_self_hosted_etcd}"
|
cluster_domain_suffix = "${var.cluster_domain_suffix}"
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,11 @@ storage:
|
|||||||
systemctl reboot
|
systemctl reboot
|
||||||
passwd:
|
passwd:
|
||||||
users:
|
users:
|
||||||
- name: core
|
# Avoid using standard name "core" so terraform apply cannot SSH until post-install.
|
||||||
|
- name: debug
|
||||||
|
create:
|
||||||
|
groups:
|
||||||
|
- sudo
|
||||||
|
- docker
|
||||||
ssh_authorized_keys:
|
ssh_authorized_keys:
|
||||||
- {{.ssh_authorized_key}}
|
- {{.ssh_authorized_key}}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
systemd:
|
systemd:
|
||||||
units:
|
units:
|
||||||
{{ if eq .etcd_on_host "true" }}
|
|
||||||
- name: etcd-member.service
|
- name: etcd-member.service
|
||||||
enable: true
|
enable: true
|
||||||
dropins:
|
dropins:
|
||||||
@ -9,12 +8,12 @@ systemd:
|
|||||||
contents: |
|
contents: |
|
||||||
[Service]
|
[Service]
|
||||||
Environment="ETCD_IMAGE_TAG=v3.2.0"
|
Environment="ETCD_IMAGE_TAG=v3.2.0"
|
||||||
Environment="ETCD_NAME={{.etcd_name}}"
|
Environment="ETCD_NAME=${etcd_name}"
|
||||||
Environment="ETCD_ADVERTISE_CLIENT_URLS=https://{{.domain_name}}:2379"
|
Environment="ETCD_ADVERTISE_CLIENT_URLS=https://${domain_name}:2379"
|
||||||
Environment="ETCD_INITIAL_ADVERTISE_PEER_URLS=https://{{.domain_name}}:2380"
|
Environment="ETCD_INITIAL_ADVERTISE_PEER_URLS=https://${domain_name}:2380"
|
||||||
Environment="ETCD_LISTEN_CLIENT_URLS=https://0.0.0.0:2379"
|
Environment="ETCD_LISTEN_CLIENT_URLS=https://0.0.0.0:2379"
|
||||||
Environment="ETCD_LISTEN_PEER_URLS=https://0.0.0.0:2380"
|
Environment="ETCD_LISTEN_PEER_URLS=https://0.0.0.0:2380"
|
||||||
Environment="ETCD_INITIAL_CLUSTER={{.etcd_initial_cluster}}"
|
Environment="ETCD_INITIAL_CLUSTER=${etcd_initial_cluster}"
|
||||||
Environment="ETCD_STRICT_RECONFIG_CHECK=true"
|
Environment="ETCD_STRICT_RECONFIG_CHECK=true"
|
||||||
Environment="ETCD_SSL_DIR=/etc/ssl/etcd"
|
Environment="ETCD_SSL_DIR=/etc/ssl/etcd"
|
||||||
Environment="ETCD_TRUSTED_CA_FILE=/etc/ssl/certs/etcd/server-ca.crt"
|
Environment="ETCD_TRUSTED_CA_FILE=/etc/ssl/certs/etcd/server-ca.crt"
|
||||||
@ -25,7 +24,6 @@ systemd:
|
|||||||
Environment="ETCD_PEER_CERT_FILE=/etc/ssl/certs/etcd/peer.crt"
|
Environment="ETCD_PEER_CERT_FILE=/etc/ssl/certs/etcd/peer.crt"
|
||||||
Environment="ETCD_PEER_KEY_FILE=/etc/ssl/certs/etcd/peer.key"
|
Environment="ETCD_PEER_KEY_FILE=/etc/ssl/certs/etcd/peer.key"
|
||||||
Environment="ETCD_PEER_CLIENT_CERT_AUTH=true"
|
Environment="ETCD_PEER_CLIENT_CERT_AUTH=true"
|
||||||
{{ end }}
|
|
||||||
- name: docker.service
|
- name: docker.service
|
||||||
enable: true
|
enable: true
|
||||||
- name: locksmithd.service
|
- name: locksmithd.service
|
||||||
@ -52,43 +50,50 @@ systemd:
|
|||||||
ExecStart=/bin/sh -c 'while ! /usr/bin/grep '^[^#[:space:]]' /etc/resolv.conf > /dev/null; do sleep 1; done'
|
ExecStart=/bin/sh -c 'while ! /usr/bin/grep '^[^#[:space:]]' /etc/resolv.conf > /dev/null; do sleep 1; done'
|
||||||
[Install]
|
[Install]
|
||||||
RequiredBy=kubelet.service
|
RequiredBy=kubelet.service
|
||||||
|
RequiredBy=etcd-member.service
|
||||||
- name: kubelet.service
|
- name: kubelet.service
|
||||||
contents: |
|
contents: |
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Kubelet via Hyperkube ACI
|
Description=Kubelet via Hyperkube ACI
|
||||||
|
Wants=rpc-statd.service
|
||||||
[Service]
|
[Service]
|
||||||
EnvironmentFile=/etc/kubernetes/kubelet.env
|
EnvironmentFile=/etc/kubernetes/kubelet.env
|
||||||
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/run/kubelet-pod.uuid \
|
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/cache/kubelet-pod.uuid \
|
||||||
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
||||||
--mount volume=resolv,target=/etc/resolv.conf \
|
--mount volume=resolv,target=/etc/resolv.conf \
|
||||||
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
||||||
--mount volume=var-lib-cni,target=/var/lib/cni \
|
--mount volume=var-lib-cni,target=/var/lib/cni \
|
||||||
|
--volume opt-cni-bin,kind=host,source=/opt/cni/bin \
|
||||||
|
--mount volume=opt-cni-bin,target=/opt/cni/bin \
|
||||||
--volume var-log,kind=host,source=/var/log \
|
--volume var-log,kind=host,source=/var/log \
|
||||||
--mount volume=var-log,target=/var/log"
|
--mount volume=var-log,target=/var/log \
|
||||||
|
--insecure-options=image"
|
||||||
|
ExecStartPre=/bin/mkdir -p /opt/cni/bin
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
||||||
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
||||||
|
ExecStartPre=/bin/mkdir -p /var/lib/kubelet/volumeplugins
|
||||||
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
||||||
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/run/kubelet-pod.uuid
|
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
||||||
--kubeconfig=/etc/kubernetes/kubeconfig \
|
|
||||||
--require-kubeconfig \
|
|
||||||
--client-ca-file=/etc/kubernetes/ca.crt \
|
|
||||||
--anonymous-auth=false \
|
|
||||||
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
|
||||||
--network-plugin=cni \
|
|
||||||
--lock-file=/var/run/lock/kubelet.lock \
|
|
||||||
--exit-on-lock-contention \
|
|
||||||
--pod-manifest-path=/etc/kubernetes/manifests \
|
|
||||||
--allow-privileged \
|
--allow-privileged \
|
||||||
--hostname-override={{.domain_name}} \
|
--anonymous-auth=false \
|
||||||
|
--client-ca-file=/etc/kubernetes/ca.crt \
|
||||||
|
--cluster_dns=${k8s_dns_service_ip} \
|
||||||
|
--cluster_domain=${cluster_domain_suffix} \
|
||||||
|
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
||||||
|
--exit-on-lock-contention \
|
||||||
|
--hostname-override=${domain_name} \
|
||||||
|
--kubeconfig=/etc/kubernetes/kubeconfig \
|
||||||
|
--lock-file=/var/run/lock/kubelet.lock \
|
||||||
|
--network-plugin=cni \
|
||||||
--node-labels=node-role.kubernetes.io/master \
|
--node-labels=node-role.kubernetes.io/master \
|
||||||
|
--pod-manifest-path=/etc/kubernetes/manifests \
|
||||||
--register-with-taints=node-role.kubernetes.io/master=:NoSchedule \
|
--register-with-taints=node-role.kubernetes.io/master=:NoSchedule \
|
||||||
--cluster_dns={{.k8s_dns_service_ip}} \
|
--volume-plugin-dir=/var/lib/kubelet/volumeplugins
|
||||||
--cluster_domain=cluster.local
|
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/run/kubelet-pod.uuid
|
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=10
|
RestartSec=10
|
||||||
[Install]
|
[Install]
|
||||||
@ -105,36 +110,20 @@ systemd:
|
|||||||
ExecStart=/opt/bootkube/bootkube-start
|
ExecStart=/opt/bootkube/bootkube-start
|
||||||
ExecStartPost=/bin/touch /opt/bootkube/init_bootkube.done
|
ExecStartPost=/bin/touch /opt/bootkube/init_bootkube.done
|
||||||
storage:
|
storage:
|
||||||
{{ if index . "pxe" }}
|
|
||||||
disks:
|
|
||||||
- device: /dev/sda
|
|
||||||
wipe_table: true
|
|
||||||
partitions:
|
|
||||||
- label: ROOT
|
|
||||||
filesystems:
|
|
||||||
- name: root
|
|
||||||
mount:
|
|
||||||
device: "/dev/sda1"
|
|
||||||
format: "ext4"
|
|
||||||
create:
|
|
||||||
force: true
|
|
||||||
options:
|
|
||||||
- "-LROOT"
|
|
||||||
{{end}}
|
|
||||||
files:
|
files:
|
||||||
- path: /etc/kubernetes/kubelet.env
|
- path: /etc/kubernetes/kubelet.env
|
||||||
filesystem: root
|
filesystem: root
|
||||||
mode: 0644
|
mode: 0644
|
||||||
contents:
|
contents:
|
||||||
inline: |
|
inline: |
|
||||||
KUBELET_IMAGE_URL=quay.io/coreos/hyperkube
|
KUBELET_IMAGE_URL=docker://gcr.io/google_containers/hyperkube
|
||||||
KUBELET_IMAGE_TAG=v1.7.3_coreos.0
|
KUBELET_IMAGE_TAG=v1.8.6
|
||||||
- path: /etc/hostname
|
- path: /etc/hostname
|
||||||
filesystem: root
|
filesystem: root
|
||||||
mode: 0644
|
mode: 0644
|
||||||
contents:
|
contents:
|
||||||
inline:
|
inline:
|
||||||
{{.domain_name}}
|
${domain_name}
|
||||||
- path: /etc/sysctl.d/max-user-watches.conf
|
- path: /etc/sysctl.d/max-user-watches.conf
|
||||||
filesystem: root
|
filesystem: root
|
||||||
contents:
|
contents:
|
||||||
@ -153,26 +142,25 @@ storage:
|
|||||||
# Wrapper for bootkube start
|
# Wrapper for bootkube start
|
||||||
set -e
|
set -e
|
||||||
# Move experimental manifests
|
# Move experimental manifests
|
||||||
[ -d /opt/bootkube/assets/manifests-* ] && mv /opt/bootkube/assets/manifests-*/* /opt/bootkube/assets/manifests && rm -rf /opt/bootkube/assets/manifests-*
|
[ -n "$(ls /opt/bootkube/assets/manifests-*/* 2>/dev/null)" ] && mv /opt/bootkube/assets/manifests-*/* /opt/bootkube/assets/manifests && rm -rf /opt/bootkube/assets/manifests-*
|
||||||
[ -d /opt/bootkube/assets/experimental/manifests ] && mv /opt/bootkube/assets/experimental/manifests/* /opt/bootkube/assets/manifests && rm -r /opt/bootkube/assets/experimental/manifests
|
BOOTKUBE_ACI="$${BOOTKUBE_ACI:-quay.io/coreos/bootkube}"
|
||||||
[ -d /opt/bootkube/assets/experimental/bootstrap-manifests ] && mv /opt/bootkube/assets/experimental/bootstrap-manifests/* /opt/bootkube/assets/bootstrap-manifests && rm -r /opt/bootkube/assets/experimental/bootstrap-manifests
|
BOOTKUBE_VERSION="$${BOOTKUBE_VERSION:-v0.9.1}"
|
||||||
BOOTKUBE_ACI="${BOOTKUBE_ACI:-quay.io/coreos/bootkube}"
|
BOOTKUBE_ASSETS="$${BOOTKUBE_ASSETS:-/opt/bootkube/assets}"
|
||||||
BOOTKUBE_VERSION="${BOOTKUBE_VERSION:-v0.6.1}"
|
|
||||||
BOOTKUBE_ASSETS="${BOOTKUBE_ASSETS:-/opt/bootkube/assets}"
|
|
||||||
exec /usr/bin/rkt run \
|
exec /usr/bin/rkt run \
|
||||||
--trust-keys-from-https \
|
--trust-keys-from-https \
|
||||||
--volume assets,kind=host,source=$BOOTKUBE_ASSETS \
|
--volume assets,kind=host,source=$BOOTKUBE_ASSETS \
|
||||||
--mount volume=assets,target=/assets \
|
--mount volume=assets,target=/assets \
|
||||||
--volume bootstrap,kind=host,source=/etc/kubernetes \
|
--volume bootstrap,kind=host,source=/etc/kubernetes \
|
||||||
--mount volume=bootstrap,target=/etc/kubernetes \
|
--mount volume=bootstrap,target=/etc/kubernetes \
|
||||||
$RKT_OPTS \
|
$$RKT_OPTS \
|
||||||
${BOOTKUBE_ACI}:${BOOTKUBE_VERSION} \
|
$${BOOTKUBE_ACI}:$${BOOTKUBE_VERSION} \
|
||||||
--net=host \
|
--net=host \
|
||||||
--dns=host \
|
--dns=host \
|
||||||
--exec=/bootkube -- start --asset-dir=/assets "$@"
|
--exec=/bootkube -- start --asset-dir=/assets "$@"
|
||||||
|
networkd:
|
||||||
|
${networkd_content}
|
||||||
passwd:
|
passwd:
|
||||||
users:
|
users:
|
||||||
- name: core
|
- name: core
|
||||||
ssh_authorized_keys:
|
ssh_authorized_keys:
|
||||||
- {{.ssh_authorized_key}}
|
- ${ssh_authorized_key}
|
||||||
|
|
||||||
|
@ -31,82 +31,74 @@ systemd:
|
|||||||
contents: |
|
contents: |
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Kubelet via Hyperkube ACI
|
Description=Kubelet via Hyperkube ACI
|
||||||
|
Wants=rpc-statd.service
|
||||||
[Service]
|
[Service]
|
||||||
EnvironmentFile=/etc/kubernetes/kubelet.env
|
EnvironmentFile=/etc/kubernetes/kubelet.env
|
||||||
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/run/kubelet-pod.uuid \
|
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/cache/kubelet-pod.uuid \
|
||||||
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
||||||
--mount volume=resolv,target=/etc/resolv.conf \
|
--mount volume=resolv,target=/etc/resolv.conf \
|
||||||
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
||||||
--mount volume=var-lib-cni,target=/var/lib/cni \
|
--mount volume=var-lib-cni,target=/var/lib/cni \
|
||||||
|
--volume opt-cni-bin,kind=host,source=/opt/cni/bin \
|
||||||
|
--mount volume=opt-cni-bin,target=/opt/cni/bin \
|
||||||
--volume var-log,kind=host,source=/var/log \
|
--volume var-log,kind=host,source=/var/log \
|
||||||
--mount volume=var-log,target=/var/log"
|
--mount volume=var-log,target=/var/log \
|
||||||
|
--insecure-options=image"
|
||||||
|
ExecStartPre=/bin/mkdir -p /opt/cni/bin
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
||||||
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
||||||
|
ExecStartPre=/bin/mkdir -p /var/lib/kubelet/volumeplugins
|
||||||
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
||||||
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/run/kubelet-pod.uuid
|
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
||||||
--kubeconfig=/etc/kubernetes/kubeconfig \
|
|
||||||
--require-kubeconfig \
|
|
||||||
--client-ca-file=/etc/kubernetes/ca.crt \
|
|
||||||
--anonymous-auth=false \
|
|
||||||
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
|
||||||
--network-plugin=cni \
|
|
||||||
--lock-file=/var/run/lock/kubelet.lock \
|
|
||||||
--exit-on-lock-contention \
|
|
||||||
--pod-manifest-path=/etc/kubernetes/manifests \
|
|
||||||
--allow-privileged \
|
--allow-privileged \
|
||||||
--hostname-override={{.domain_name}} \
|
--anonymous-auth=false \
|
||||||
|
--client-ca-file=/etc/kubernetes/ca.crt \
|
||||||
|
--cluster_dns=${k8s_dns_service_ip} \
|
||||||
|
--cluster_domain=${cluster_domain_suffix} \
|
||||||
|
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
||||||
|
--exit-on-lock-contention \
|
||||||
|
--hostname-override=${domain_name} \
|
||||||
|
--kubeconfig=/etc/kubernetes/kubeconfig \
|
||||||
|
--lock-file=/var/run/lock/kubelet.lock \
|
||||||
|
--network-plugin=cni \
|
||||||
--node-labels=node-role.kubernetes.io/node \
|
--node-labels=node-role.kubernetes.io/node \
|
||||||
--cluster_dns={{.k8s_dns_service_ip}} \
|
--pod-manifest-path=/etc/kubernetes/manifests \
|
||||||
--cluster_domain=cluster.local
|
--volume-plugin-dir=/var/lib/kubelet/volumeplugins
|
||||||
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/run/kubelet-pod.uuid
|
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|
||||||
storage:
|
storage:
|
||||||
{{ if index . "pxe" }}
|
|
||||||
disks:
|
|
||||||
- device: /dev/sda
|
|
||||||
wipe_table: true
|
|
||||||
partitions:
|
|
||||||
- label: ROOT
|
|
||||||
filesystems:
|
|
||||||
- name: root
|
|
||||||
mount:
|
|
||||||
device: "/dev/sda1"
|
|
||||||
format: "ext4"
|
|
||||||
create:
|
|
||||||
force: true
|
|
||||||
options:
|
|
||||||
- "-LROOT"
|
|
||||||
{{end}}
|
|
||||||
files:
|
files:
|
||||||
- path: /etc/kubernetes/kubelet.env
|
- path: /etc/kubernetes/kubelet.env
|
||||||
filesystem: root
|
filesystem: root
|
||||||
mode: 0644
|
mode: 0644
|
||||||
contents:
|
contents:
|
||||||
inline: |
|
inline: |
|
||||||
KUBELET_IMAGE_URL=quay.io/coreos/hyperkube
|
KUBELET_IMAGE_URL=docker://gcr.io/google_containers/hyperkube
|
||||||
KUBELET_IMAGE_TAG=v1.7.3_coreos.0
|
KUBELET_IMAGE_TAG=v1.8.6
|
||||||
- path: /etc/hostname
|
- path: /etc/hostname
|
||||||
filesystem: root
|
filesystem: root
|
||||||
mode: 0644
|
mode: 0644
|
||||||
contents:
|
contents:
|
||||||
inline:
|
inline:
|
||||||
{{.domain_name}}
|
${domain_name}
|
||||||
- path: /etc/sysctl.d/max-user-watches.conf
|
- path: /etc/sysctl.d/max-user-watches.conf
|
||||||
filesystem: root
|
filesystem: root
|
||||||
contents:
|
contents:
|
||||||
inline: |
|
inline: |
|
||||||
fs.inotify.max_user_watches=16184
|
fs.inotify.max_user_watches=16184
|
||||||
|
networkd:
|
||||||
|
${networkd_content}
|
||||||
passwd:
|
passwd:
|
||||||
users:
|
users:
|
||||||
- name: core
|
- name: core
|
||||||
ssh_authorized_keys:
|
ssh_authorized_keys:
|
||||||
- {{.ssh_authorized_key}}
|
- ${ssh_authorized_key}
|
||||||
|
|
||||||
|
@ -17,37 +17,21 @@ resource "matchbox_group" "container-linux-install" {
|
|||||||
resource "matchbox_group" "controller" {
|
resource "matchbox_group" "controller" {
|
||||||
count = "${length(var.controller_names)}"
|
count = "${length(var.controller_names)}"
|
||||||
name = "${format("%s-%s", var.cluster_name, element(var.controller_names, count.index))}"
|
name = "${format("%s-%s", var.cluster_name, element(var.controller_names, count.index))}"
|
||||||
profile = "${matchbox_profile.controller.name}"
|
profile = "${element(matchbox_profile.controllers.*.name, count.index)}"
|
||||||
|
|
||||||
selector {
|
selector {
|
||||||
mac = "${element(var.controller_macs, count.index)}"
|
mac = "${element(var.controller_macs, count.index)}"
|
||||||
os = "installed"
|
os = "installed"
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata {
|
|
||||||
domain_name = "${element(var.controller_domains, count.index)}"
|
|
||||||
etcd_name = "${element(var.controller_names, count.index)}"
|
|
||||||
etcd_initial_cluster = "${join(",", formatlist("%s=https://%s:2380", var.controller_names, var.controller_domains))}"
|
|
||||||
etcd_on_host = "${var.experimental_self_hosted_etcd ? "false" : "true"}"
|
|
||||||
k8s_dns_service_ip = "${module.bootkube.kube_dns_service_ip}"
|
|
||||||
ssh_authorized_key = "${var.ssh_authorized_key}"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "matchbox_group" "worker" {
|
resource "matchbox_group" "worker" {
|
||||||
count = "${length(var.worker_names)}"
|
count = "${length(var.worker_names)}"
|
||||||
name = "${format("%s-%s", var.cluster_name, element(var.worker_names, count.index))}"
|
name = "${format("%s-%s", var.cluster_name, element(var.worker_names, count.index))}"
|
||||||
profile = "${matchbox_profile.worker.name}"
|
profile = "${element(matchbox_profile.workers.*.name, count.index)}"
|
||||||
|
|
||||||
selector {
|
selector {
|
||||||
mac = "${element(var.worker_macs, count.index)}"
|
mac = "${element(var.worker_macs, count.index)}"
|
||||||
os = "installed"
|
os = "installed"
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata {
|
|
||||||
domain_name = "${element(var.worker_domains, count.index)}"
|
|
||||||
etcd_on_host = "${var.experimental_self_hosted_etcd ? "false" : "true"}"
|
|
||||||
k8s_dns_service_ip = "${module.bootkube.kube_dns_service_ip}"
|
|
||||||
ssh_authorized_key = "${var.ssh_authorized_key}"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,12 @@ resource "matchbox_profile" "container-linux-install" {
|
|||||||
]
|
]
|
||||||
|
|
||||||
args = [
|
args = [
|
||||||
|
"initrd=coreos_production_pxe_image.cpio.gz",
|
||||||
"coreos.config.url=${var.matchbox_http_endpoint}/ignition?uuid=$${uuid}&mac=$${mac:hexhyp}",
|
"coreos.config.url=${var.matchbox_http_endpoint}/ignition?uuid=$${uuid}&mac=$${mac:hexhyp}",
|
||||||
"coreos.first_boot=yes",
|
"coreos.first_boot=yes",
|
||||||
"console=tty0",
|
"console=tty0",
|
||||||
"console=ttyS0",
|
"console=ttyS0",
|
||||||
|
"${var.kernel_args}",
|
||||||
]
|
]
|
||||||
|
|
||||||
container_linux_config = "${data.template_file.container-linux-install-config.rendered}"
|
container_linux_config = "${data.template_file.container-linux-install-config.rendered}"
|
||||||
@ -43,10 +45,12 @@ resource "matchbox_profile" "cached-container-linux-install" {
|
|||||||
]
|
]
|
||||||
|
|
||||||
args = [
|
args = [
|
||||||
|
"initrd=coreos_production_pxe_image.cpio.gz",
|
||||||
"coreos.config.url=${var.matchbox_http_endpoint}/ignition?uuid=$${uuid}&mac=$${mac:hexhyp}",
|
"coreos.config.url=${var.matchbox_http_endpoint}/ignition?uuid=$${uuid}&mac=$${mac:hexhyp}",
|
||||||
"coreos.first_boot=yes",
|
"coreos.first_boot=yes",
|
||||||
"console=tty0",
|
"console=tty0",
|
||||||
"console=ttyS0",
|
"console=ttyS0",
|
||||||
|
"${var.kernel_args}",
|
||||||
]
|
]
|
||||||
|
|
||||||
container_linux_config = "${data.template_file.cached-container-linux-install-config.rendered}"
|
container_linux_config = "${data.template_file.cached-container-linux-install-config.rendered}"
|
||||||
@ -67,14 +71,50 @@ data "template_file" "cached-container-linux-install-config" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kubernetes Controller profile
|
// Kubernetes Controller profiles
|
||||||
resource "matchbox_profile" "controller" {
|
resource "matchbox_profile" "controllers" {
|
||||||
name = "controller"
|
count = "${length(var.controller_names)}"
|
||||||
container_linux_config = "${file("${path.module}/cl/controller.yaml.tmpl")}"
|
name = "${format("%s-controller-%s", var.cluster_name, element(var.controller_names, count.index))}"
|
||||||
|
container_linux_config = "${element(data.template_file.controller-configs.*.rendered, count.index)}"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kubernetes Worker profile
|
data "template_file" "controller-configs" {
|
||||||
resource "matchbox_profile" "worker" {
|
count = "${length(var.controller_names)}"
|
||||||
name = "worker"
|
|
||||||
container_linux_config = "${file("${path.module}/cl/worker.yaml.tmpl")}"
|
template = "${file("${path.module}/cl/controller.yaml.tmpl")}"
|
||||||
|
|
||||||
|
vars {
|
||||||
|
domain_name = "${element(var.controller_domains, count.index)}"
|
||||||
|
etcd_name = "${element(var.controller_names, count.index)}"
|
||||||
|
etcd_initial_cluster = "${join(",", formatlist("%s=https://%s:2380", var.controller_names, var.controller_domains))}"
|
||||||
|
k8s_dns_service_ip = "${module.bootkube.kube_dns_service_ip}"
|
||||||
|
cluster_domain_suffix = "${var.cluster_domain_suffix}"
|
||||||
|
ssh_authorized_key = "${var.ssh_authorized_key}"
|
||||||
|
|
||||||
|
# Terraform evaluates both sides regardless and element cannot be used on 0 length lists
|
||||||
|
networkd_content = "${length(var.controller_networkds) == 0 ? "" : element(concat(var.controller_networkds, list("")), count.index)}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kubernetes Worker profiles
|
||||||
|
resource "matchbox_profile" "workers" {
|
||||||
|
count = "${length(var.worker_names)}"
|
||||||
|
name = "${format("%s-worker-%s", var.cluster_name, element(var.worker_names, count.index))}"
|
||||||
|
container_linux_config = "${element(data.template_file.worker-configs.*.rendered, count.index)}"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "template_file" "worker-configs" {
|
||||||
|
count = "${length(var.worker_names)}"
|
||||||
|
|
||||||
|
template = "${file("${path.module}/cl/worker.yaml.tmpl")}"
|
||||||
|
|
||||||
|
vars {
|
||||||
|
domain_name = "${element(var.worker_domains, count.index)}"
|
||||||
|
k8s_dns_service_ip = "${module.bootkube.kube_dns_service_ip}"
|
||||||
|
cluster_domain_suffix = "${var.cluster_domain_suffix}"
|
||||||
|
ssh_authorized_key = "${var.ssh_authorized_key}"
|
||||||
|
|
||||||
|
# Terraform evaluates both sides regardless and element cannot be used on 0 length lists
|
||||||
|
networkd_content = "${length(var.worker_networkds) == 0 ? "" : element(concat(var.worker_networkds, list("")), count.index)}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
21
bare-metal/container-linux/kubernetes/require.tf
Normal file
21
bare-metal/container-linux/kubernetes/require.tf
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Terraform version and plugin versions
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.10.4"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "local" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "null" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "template" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "tls" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
# Secure copy etcd TLS assets and kubeconfig to all nodes. Activates kubelet.service
|
# Secure copy etcd TLS assets and kubeconfig to controllers. Activates kubelet.service
|
||||||
resource "null_resource" "copy-secrets" {
|
resource "null_resource" "copy-etcd-secrets" {
|
||||||
count = "${length(var.controller_names) + length(var.worker_names)}"
|
count = "${length(var.controller_names)}"
|
||||||
|
|
||||||
connection {
|
connection {
|
||||||
type = "ssh"
|
type = "ssh"
|
||||||
host = "${element(concat(var.controller_domains, var.worker_domains), count.index)}"
|
host = "${element(var.controller_domains, count.index)}"
|
||||||
user = "core"
|
user = "core"
|
||||||
timeout = "60m"
|
timeout = "60m"
|
||||||
}
|
}
|
||||||
@ -66,20 +66,42 @@ resource "null_resource" "copy-secrets" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Secure copy kubeconfig to all workers. Activates kubelet.service
|
||||||
|
resource "null_resource" "copy-kubeconfig" {
|
||||||
|
count = "${length(var.worker_names)}"
|
||||||
|
|
||||||
|
connection {
|
||||||
|
type = "ssh"
|
||||||
|
host = "${element(var.worker_domains, count.index)}"
|
||||||
|
user = "core"
|
||||||
|
timeout = "60m"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.kubeconfig}"
|
||||||
|
destination = "$HOME/kubeconfig"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
inline = [
|
||||||
|
"sudo mv /home/core/kubeconfig /etc/kubernetes/kubeconfig",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Secure copy bootkube assets to ONE controller and start bootkube to perform
|
# Secure copy bootkube assets to ONE controller and start bootkube to perform
|
||||||
# one-time self-hosted cluster bootstrapping.
|
# one-time self-hosted cluster bootstrapping.
|
||||||
resource "null_resource" "bootkube-start" {
|
resource "null_resource" "bootkube-start" {
|
||||||
# Without depends_on, this remote-exec may start before the kubeconfig copy.
|
# Without depends_on, this remote-exec may start before the kubeconfig copy.
|
||||||
# Terraform only does one task at a time, so it would try to bootstrap
|
# Terraform only does one task at a time, so it would try to bootstrap
|
||||||
# Kubernetes and Tectonic while no Kubelets are running. Ensure all nodes
|
# while no Kubelets are running.
|
||||||
# receive a kubeconfig before proceeding with bootkube.
|
depends_on = ["null_resource.copy-etcd-secrets", "null_resource.copy-kubeconfig"]
|
||||||
depends_on = ["null_resource.copy-secrets"]
|
|
||||||
|
|
||||||
connection {
|
connection {
|
||||||
type = "ssh"
|
type = "ssh"
|
||||||
host = "${element(var.controller_domains, 0)}"
|
host = "${element(var.controller_domains, 0)}"
|
||||||
user = "core"
|
user = "core"
|
||||||
timeout = "60m"
|
timeout = "30m"
|
||||||
}
|
}
|
||||||
|
|
||||||
provisioner "file" {
|
provisioner "file" {
|
||||||
|
@ -65,7 +65,7 @@ variable "asset_dir" {
|
|||||||
variable "networking" {
|
variable "networking" {
|
||||||
description = "Choice of networking provider (flannel or calico)"
|
description = "Choice of networking provider (flannel or calico)"
|
||||||
type = "string"
|
type = "string"
|
||||||
default = "flannel"
|
default = "calico"
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "network_mtu" {
|
variable "network_mtu" {
|
||||||
@ -83,7 +83,7 @@ variable "pod_cidr" {
|
|||||||
variable "service_cidr" {
|
variable "service_cidr" {
|
||||||
description = <<EOD
|
description = <<EOD
|
||||||
CIDR IP range to assign Kubernetes services.
|
CIDR IP range to assign Kubernetes services.
|
||||||
The 1st IP will be reserved for kube_apiserver, the 10th IP will be reserved for kube-dns, the 15th IP will be reserved for self-hosted etcd, and the 200th IP will be reserved for bootstrap self-hosted etcd.
|
The 1st IP will be reserved for kube_apiserver, the 10th IP will be reserved for kube-dns.
|
||||||
EOD
|
EOD
|
||||||
|
|
||||||
type = "string"
|
type = "string"
|
||||||
@ -92,6 +92,12 @@ EOD
|
|||||||
|
|
||||||
# optional
|
# optional
|
||||||
|
|
||||||
|
variable "cluster_domain_suffix" {
|
||||||
|
description = "Queries for domains with the suffix will be answered by kube-dns. Default is cluster.local (e.g. foo.default.svc.cluster.local) "
|
||||||
|
type = "string"
|
||||||
|
default = "cluster.local"
|
||||||
|
}
|
||||||
|
|
||||||
variable "cached_install" {
|
variable "cached_install" {
|
||||||
type = "string"
|
type = "string"
|
||||||
default = "false"
|
default = "false"
|
||||||
@ -110,7 +116,22 @@ variable "container_linux_oem" {
|
|||||||
description = "Specify an OEM image id to use as base for the installation (e.g. ami, vmware_raw, xen) or leave blank for the default image"
|
description = "Specify an OEM image id to use as base for the installation (e.g. ami, vmware_raw, xen) or leave blank for the default image"
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "experimental_self_hosted_etcd" {
|
variable "kernel_args" {
|
||||||
default = "false"
|
description = "Additional kernel arguments to provide at PXE boot."
|
||||||
description = "Create self-hosted etcd cluster as pods on Kubernetes, instead of on-hosts"
|
type = "list"
|
||||||
|
default = []
|
||||||
|
}
|
||||||
|
|
||||||
|
# unofficial, undocumented, unsupported, temporary
|
||||||
|
|
||||||
|
variable "controller_networkds" {
|
||||||
|
type = "list"
|
||||||
|
description = "Controller Container Linux config networkd section"
|
||||||
|
default = []
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "worker_networkds" {
|
||||||
|
type = "list"
|
||||||
|
description = "Worker Container Linux config networkd section"
|
||||||
|
default = []
|
||||||
}
|
}
|
||||||
|
@ -31,38 +31,44 @@ systemd:
|
|||||||
contents: |
|
contents: |
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Kubelet via Hyperkube ACI
|
Description=Kubelet via Hyperkube ACI
|
||||||
|
Wants=rpc-statd.service
|
||||||
[Service]
|
[Service]
|
||||||
EnvironmentFile=/etc/kubernetes/kubelet.env
|
EnvironmentFile=/etc/kubernetes/kubelet.env
|
||||||
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/run/kubelet-pod.uuid \
|
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/cache/kubelet-pod.uuid \
|
||||||
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
||||||
--mount volume=resolv,target=/etc/resolv.conf \
|
--mount volume=resolv,target=/etc/resolv.conf \
|
||||||
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
||||||
--mount volume=var-lib-cni,target=/var/lib/cni \
|
--mount volume=var-lib-cni,target=/var/lib/cni \
|
||||||
|
--volume opt-cni-bin,kind=host,source=/opt/cni/bin \
|
||||||
|
--mount volume=opt-cni-bin,target=/opt/cni/bin \
|
||||||
--volume var-log,kind=host,source=/var/log \
|
--volume var-log,kind=host,source=/var/log \
|
||||||
--mount volume=var-log,target=/var/log"
|
--mount volume=var-log,target=/var/log \
|
||||||
|
--insecure-options=image"
|
||||||
|
ExecStartPre=/bin/mkdir -p /opt/cni/bin
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
||||||
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
||||||
|
ExecStartPre=/bin/mkdir -p /var/lib/kubelet/volumeplugins
|
||||||
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
||||||
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/run/kubelet-pod.uuid
|
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
||||||
--kubeconfig=/etc/kubernetes/kubeconfig \
|
|
||||||
--require-kubeconfig \
|
|
||||||
--client-ca-file=/etc/kubernetes/ca.crt \
|
|
||||||
--anonymous-auth=false \
|
|
||||||
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
|
||||||
--network-plugin=cni \
|
|
||||||
--lock-file=/var/run/lock/kubelet.lock \
|
|
||||||
--exit-on-lock-contention \
|
|
||||||
--pod-manifest-path=/etc/kubernetes/manifests \
|
|
||||||
--allow-privileged \
|
--allow-privileged \
|
||||||
--hostname-override={{.domain_name}} \
|
--anonymous-auth=false \
|
||||||
--node-labels=node-role.kubernetes.io/node \
|
--client-ca-file=/etc/kubernetes/ca.crt \
|
||||||
--cluster_dns={{.k8s_dns_service_ip}} \
|
--cluster_dns={{.k8s_dns_service_ip}} \
|
||||||
--cluster_domain=cluster.local
|
--cluster_domain={{.cluster_domain_suffix}} \
|
||||||
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/run/kubelet-pod.uuid
|
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
||||||
|
--exit-on-lock-contention \
|
||||||
|
--hostname-override={{.domain_name}} \
|
||||||
|
--kubeconfig=/etc/kubernetes/kubeconfig \
|
||||||
|
--lock-file=/var/run/lock/kubelet.lock \
|
||||||
|
--network-plugin=cni \
|
||||||
|
--node-labels=node-role.kubernetes.io/node \
|
||||||
|
--pod-manifest-path=/etc/kubernetes/manifests \
|
||||||
|
--volume-plugin-dir=/var/lib/kubelet/volumeplugins
|
||||||
|
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
[Install]
|
[Install]
|
||||||
@ -91,8 +97,8 @@ storage:
|
|||||||
mode: 0644
|
mode: 0644
|
||||||
contents:
|
contents:
|
||||||
inline: |
|
inline: |
|
||||||
KUBELET_IMAGE_URL=quay.io/coreos/hyperkube
|
KUBELET_IMAGE_URL=docker://gcr.io/google_containers/hyperkube
|
||||||
KUBELET_IMAGE_TAG=v1.7.3_coreos.0
|
KUBELET_IMAGE_TAG=v1.8.6
|
||||||
- path: /etc/hostname
|
- path: /etc/hostname
|
||||||
filesystem: root
|
filesystem: root
|
||||||
mode: 0644
|
mode: 0644
|
||||||
|
@ -16,6 +16,7 @@ resource "matchbox_group" "workers" {
|
|||||||
etcd_on_host = "true"
|
etcd_on_host = "true"
|
||||||
k8s_etcd_service_ip = "10.3.0.15"
|
k8s_etcd_service_ip = "10.3.0.15"
|
||||||
k8s_dns_service_ip = "${var.kube_dns_service_ip}"
|
k8s_dns_service_ip = "${var.kube_dns_service_ip}"
|
||||||
|
cluster_domain_suffix = "${var.cluster_domain_suffix}"
|
||||||
ssh_authorized_key = "${var.ssh_authorized_key}"
|
ssh_authorized_key = "${var.ssh_authorized_key}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,12 @@ resource "matchbox_profile" "bootkube-worker-pxe" {
|
|||||||
]
|
]
|
||||||
|
|
||||||
args = [
|
args = [
|
||||||
"root=/dev/sda1",
|
"initrd=coreos_production_pxe_image.cpio.gz",
|
||||||
"coreos.config.url=${var.matchbox_http_endpoint}/ignition?uuid=$${uuid}&mac=$${mac:hexhyp}",
|
"coreos.config.url=${var.matchbox_http_endpoint}/ignition?uuid=$${uuid}&mac=$${mac:hexhyp}",
|
||||||
"coreos.first_boot=yes",
|
"coreos.first_boot=yes",
|
||||||
"console=tty0",
|
"console=tty0",
|
||||||
"console=ttyS0",
|
"console=ttyS0",
|
||||||
"kvm-intel.nested=1",
|
"${var.kernel_args}",
|
||||||
]
|
]
|
||||||
|
|
||||||
container_linux_config = "${file("${path.module}/cl/bootkube-worker.yaml.tmpl")}"
|
container_linux_config = "${file("${path.module}/cl/bootkube-worker.yaml.tmpl")}"
|
||||||
|
@ -53,3 +53,20 @@ variable "kube_dns_service_ip" {
|
|||||||
type = "string"
|
type = "string"
|
||||||
default = "10.3.0.10"
|
default = "10.3.0.10"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# optional
|
||||||
|
|
||||||
|
variable "kernel_args" {
|
||||||
|
description = "Additional kernel arguments to provide at PXE boot."
|
||||||
|
type = "list"
|
||||||
|
|
||||||
|
default = [
|
||||||
|
"root=/dev/sda1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "cluster_domain_suffix" {
|
||||||
|
description = "Queries for domains with the suffix will be answered by kube-dns. Default is cluster.local (e.g. foo.default.svc.cluster.local) "
|
||||||
|
type = "string"
|
||||||
|
default = "cluster.local"
|
||||||
|
}
|
||||||
|
23
digital-ocean/container-linux/kubernetes/LICENSE
Normal file
23
digital-ocean/container-linux/kubernetes/LICENSE
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2017 Typhoon Authors
|
||||||
|
Copyright (c) 2017 Dalton Hubble
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
22
digital-ocean/container-linux/kubernetes/README.md
Normal file
22
digital-ocean/container-linux/kubernetes/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Typhoon <img align="right" src="https://storage.googleapis.com/poseidon/typhoon-logo.png">
|
||||||
|
|
||||||
|
Typhoon is a minimal and free Kubernetes distribution.
|
||||||
|
|
||||||
|
* Minimal, stable base Kubernetes distribution
|
||||||
|
* Declarative infrastructure and configuration
|
||||||
|
* Free (freedom and cost) and privacy-respecting
|
||||||
|
* Practical for labs, datacenters, and clouds
|
||||||
|
|
||||||
|
Typhoon distributes upstream Kubernetes, architectural conventions, and cluster addons, much like a GNU/Linux distribution provides the Linux kernel and userspace components.
|
||||||
|
|
||||||
|
## Features <a href="https://www.cncf.io/certification/software-conformance/"><img align="right" src="https://storage.googleapis.com/poseidon/certified-kubernetes.png"></a>
|
||||||
|
|
||||||
|
* Kubernetes v1.8.6 (upstream, via [kubernetes-incubator/bootkube](https://github.com/kubernetes-incubator/bootkube))
|
||||||
|
* Single or multi-master, workloads isolated on workers, [Calico](https://www.projectcalico.org/) or [flannel](https://github.com/coreos/flannel) networking
|
||||||
|
* On-cluster etcd with TLS, [RBAC](https://kubernetes.io/docs/admin/authorization/rbac/)-enabled, [network policy](https://kubernetes.io/docs/concepts/services-networking/network-policies/)
|
||||||
|
* Ready for Ingress, Dashboards, Metrics, and other optional [addons](https://typhoon.psdn.io/addons/overview/)
|
||||||
|
|
||||||
|
## Docs
|
||||||
|
|
||||||
|
Please see the [official docs](https://typhoon.psdn.io) and the Digital Ocean [tutorial](https://typhoon.psdn.io/digital-ocean/).
|
||||||
|
|
@ -1,14 +1,14 @@
|
|||||||
# Self-hosted Kubernetes assets (kubeconfig, manifests)
|
# Self-hosted Kubernetes assets (kubeconfig, manifests)
|
||||||
module "bootkube" {
|
module "bootkube" {
|
||||||
source = "git::https://github.com/poseidon/bootkube-terraform.git?ref=5ffbfec46dc05721eaf9d15c3c9bbedefaead1bc"
|
source = "git::https://github.com/poseidon/terraform-render-bootkube.git?ref=5072569bb7dff1c2f6bc6fb7b06ce0a41809971e"
|
||||||
|
|
||||||
cluster_name = "${var.cluster_name}"
|
cluster_name = "${var.cluster_name}"
|
||||||
api_servers = ["${format("%s.%s", var.cluster_name, var.dns_zone)}"]
|
api_servers = ["${format("%s.%s", var.cluster_name, var.dns_zone)}"]
|
||||||
etcd_servers = ["http://127.0.0.1:2379"]
|
etcd_servers = "${digitalocean_record.etcds.*.fqdn}"
|
||||||
asset_dir = "${var.asset_dir}"
|
asset_dir = "${var.asset_dir}"
|
||||||
networking = "${var.networking}"
|
networking = "${var.networking}"
|
||||||
network_mtu = 1440
|
network_mtu = 1440
|
||||||
pod_cidr = "${var.pod_cidr}"
|
pod_cidr = "${var.pod_cidr}"
|
||||||
service_cidr = "${var.service_cidr}"
|
service_cidr = "${var.service_cidr}"
|
||||||
experimental_self_hosted_etcd = "true"
|
cluster_domain_suffix = "${var.cluster_domain_suffix}"
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,42 @@
|
|||||||
---
|
---
|
||||||
systemd:
|
systemd:
|
||||||
units:
|
units:
|
||||||
|
- name: etcd-member.service
|
||||||
|
enable: true
|
||||||
|
dropins:
|
||||||
|
- name: 40-etcd-cluster.conf
|
||||||
|
contents: |
|
||||||
|
[Service]
|
||||||
|
Environment="ETCD_IMAGE_TAG=v3.2.0"
|
||||||
|
Environment="ETCD_NAME=${etcd_name}"
|
||||||
|
Environment="ETCD_ADVERTISE_CLIENT_URLS=https://${etcd_domain}:2379"
|
||||||
|
Environment="ETCD_INITIAL_ADVERTISE_PEER_URLS=https://${etcd_domain}:2380"
|
||||||
|
Environment="ETCD_LISTEN_CLIENT_URLS=https://0.0.0.0:2379"
|
||||||
|
Environment="ETCD_LISTEN_PEER_URLS=https://0.0.0.0:2380"
|
||||||
|
Environment="ETCD_INITIAL_CLUSTER=${etcd_initial_cluster}"
|
||||||
|
Environment="ETCD_STRICT_RECONFIG_CHECK=true"
|
||||||
|
Environment="ETCD_SSL_DIR=/etc/ssl/etcd"
|
||||||
|
Environment="ETCD_TRUSTED_CA_FILE=/etc/ssl/certs/etcd/server-ca.crt"
|
||||||
|
Environment="ETCD_CERT_FILE=/etc/ssl/certs/etcd/server.crt"
|
||||||
|
Environment="ETCD_KEY_FILE=/etc/ssl/certs/etcd/server.key"
|
||||||
|
Environment="ETCD_CLIENT_CERT_AUTH=true"
|
||||||
|
Environment="ETCD_PEER_TRUSTED_CA_FILE=/etc/ssl/certs/etcd/peer-ca.crt"
|
||||||
|
Environment="ETCD_PEER_CERT_FILE=/etc/ssl/certs/etcd/peer.crt"
|
||||||
|
Environment="ETCD_PEER_KEY_FILE=/etc/ssl/certs/etcd/peer.key"
|
||||||
|
Environment="ETCD_PEER_CLIENT_CERT_AUTH=true"
|
||||||
- name: docker.service
|
- name: docker.service
|
||||||
enable: true
|
enable: true
|
||||||
- name: locksmithd.service
|
- name: locksmithd.service
|
||||||
mask: true
|
mask: true
|
||||||
|
- name: kubelet.path
|
||||||
|
enable: true
|
||||||
|
contents: |
|
||||||
|
[Unit]
|
||||||
|
Description=Watch for kubeconfig
|
||||||
|
[Path]
|
||||||
|
PathExists=/etc/kubernetes/kubeconfig
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
- name: wait-for-dns.service
|
- name: wait-for-dns.service
|
||||||
enable: true
|
enable: true
|
||||||
contents: |
|
contents: |
|
||||||
@ -18,47 +50,51 @@ systemd:
|
|||||||
ExecStart=/bin/sh -c 'while ! /usr/bin/grep '^[^#[:space:]]' /etc/resolv.conf > /dev/null; do sleep 1; done'
|
ExecStart=/bin/sh -c 'while ! /usr/bin/grep '^[^#[:space:]]' /etc/resolv.conf > /dev/null; do sleep 1; done'
|
||||||
[Install]
|
[Install]
|
||||||
RequiredBy=kubelet.service
|
RequiredBy=kubelet.service
|
||||||
|
RequiredBy=etcd-member.service
|
||||||
- name: kubelet.service
|
- name: kubelet.service
|
||||||
enable: true
|
|
||||||
contents: |
|
contents: |
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Kubelet via Hyperkube ACI
|
Description=Kubelet via Hyperkube ACI
|
||||||
Requires=coreos-metadata.service
|
Requires=coreos-metadata.service
|
||||||
After=coreos-metadata.service
|
After=coreos-metadata.service
|
||||||
|
Wants=rpc-statd.service
|
||||||
[Service]
|
[Service]
|
||||||
EnvironmentFile=/etc/kubernetes/kubelet.env
|
EnvironmentFile=/etc/kubernetes/kubelet.env
|
||||||
EnvironmentFile=/run/metadata/coreos
|
EnvironmentFile=/run/metadata/coreos
|
||||||
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/run/kubelet-pod.uuid \
|
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/cache/kubelet-pod.uuid \
|
||||||
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
||||||
--mount volume=resolv,target=/etc/resolv.conf \
|
--mount volume=resolv,target=/etc/resolv.conf \
|
||||||
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
||||||
--mount volume=var-lib-cni,target=/var/lib/cni \
|
--mount volume=var-lib-cni,target=/var/lib/cni \
|
||||||
|
--volume opt-cni-bin,kind=host,source=/opt/cni/bin \
|
||||||
|
--mount volume=opt-cni-bin,target=/opt/cni/bin \
|
||||||
--volume var-log,kind=host,source=/var/log \
|
--volume var-log,kind=host,source=/var/log \
|
||||||
--mount volume=var-log,target=/var/log"
|
--mount volume=var-log,target=/var/log \
|
||||||
|
--insecure-options=image"
|
||||||
|
ExecStartPre=/bin/mkdir -p /opt/cni/bin
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
||||||
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
||||||
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
||||||
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/run/kubelet-pod.uuid
|
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
||||||
--kubeconfig=/etc/kubernetes/kubeconfig \
|
--allow-privileged \
|
||||||
--require-kubeconfig \
|
|
||||||
--client-ca-file=/etc/kubernetes/ca.crt \
|
|
||||||
--anonymous-auth=false \
|
--anonymous-auth=false \
|
||||||
|
--client-ca-file=/etc/kubernetes/ca.crt \
|
||||||
|
--cluster_dns=${k8s_dns_service_ip} \
|
||||||
|
--cluster_domain=${cluster_domain_suffix} \
|
||||||
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
||||||
--network-plugin=cni \
|
|
||||||
--lock-file=/var/run/lock/kubelet.lock \
|
|
||||||
--exit-on-lock-contention \
|
--exit-on-lock-contention \
|
||||||
--hostname-override=$${COREOS_DIGITALOCEAN_IPV4_PRIVATE_0} \
|
--hostname-override=$${COREOS_DIGITALOCEAN_IPV4_PRIVATE_0} \
|
||||||
--pod-manifest-path=/etc/kubernetes/manifests \
|
--kubeconfig=/etc/kubernetes/kubeconfig \
|
||||||
--allow-privileged \
|
--lock-file=/var/run/lock/kubelet.lock \
|
||||||
|
--network-plugin=cni \
|
||||||
--node-labels=node-role.kubernetes.io/master \
|
--node-labels=node-role.kubernetes.io/master \
|
||||||
--register-with-taints=node-role.kubernetes.io/master=:NoSchedule \
|
--pod-manifest-path=/etc/kubernetes/manifests \
|
||||||
--cluster_dns=${k8s_dns_service_ip} \
|
--register-with-taints=node-role.kubernetes.io/master=:NoSchedule
|
||||||
--cluster_domain=cluster.local
|
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/run/kubelet-pod.uuid
|
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=10
|
RestartSec=10
|
||||||
[Install]
|
[Install]
|
||||||
@ -78,34 +114,13 @@ systemd:
|
|||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
storage:
|
storage:
|
||||||
files:
|
files:
|
||||||
- path: /etc/kubernetes/kubeconfig
|
|
||||||
filesystem: root
|
|
||||||
mode: 0644
|
|
||||||
contents:
|
|
||||||
inline: |
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Config
|
|
||||||
clusters:
|
|
||||||
- name: local
|
|
||||||
cluster:
|
|
||||||
server: ${kubeconfig_server}
|
|
||||||
certificate-authority-data: ${kubeconfig_ca_cert}
|
|
||||||
users:
|
|
||||||
- name: kubelet
|
|
||||||
user:
|
|
||||||
client-certificate-data: ${kubeconfig_kubelet_cert}
|
|
||||||
client-key-data: ${kubeconfig_kubelet_key}
|
|
||||||
contexts:
|
|
||||||
- context:
|
|
||||||
cluster: local
|
|
||||||
user: kubelet
|
|
||||||
- path: /etc/kubernetes/kubelet.env
|
- path: /etc/kubernetes/kubelet.env
|
||||||
filesystem: root
|
filesystem: root
|
||||||
mode: 0644
|
mode: 0644
|
||||||
contents:
|
contents:
|
||||||
inline: |
|
inline: |
|
||||||
KUBELET_IMAGE_URL=quay.io/coreos/hyperkube
|
KUBELET_IMAGE_URL=docker://gcr.io/google_containers/hyperkube
|
||||||
KUBELET_IMAGE_TAG=v1.7.3_coreos.0
|
KUBELET_IMAGE_TAG=v1.8.6
|
||||||
- path: /etc/sysctl.d/max-user-watches.conf
|
- path: /etc/sysctl.d/max-user-watches.conf
|
||||||
filesystem: root
|
filesystem: root
|
||||||
contents:
|
contents:
|
||||||
@ -124,11 +139,9 @@ storage:
|
|||||||
# Wrapper for bootkube start
|
# Wrapper for bootkube start
|
||||||
set -e
|
set -e
|
||||||
# Move experimental manifests
|
# Move experimental manifests
|
||||||
[ -d /opt/bootkube/assets/manifests-* ] && mv /opt/bootkube/assets/manifests-*/* /opt/bootkube/assets/manifests && rm -rf /opt/bootkube/assets/manifests-*
|
[ -n "$(ls /opt/bootkube/assets/manifests-*/* 2>/dev/null)" ] && mv /opt/bootkube/assets/manifests-*/* /opt/bootkube/assets/manifests && rm -rf /opt/bootkube/assets/manifests-*
|
||||||
[ -d /opt/bootkube/assets/experimental/manifests ] && mv /opt/bootkube/assets/experimental/manifests/* /opt/bootkube/assets/manifests && rm -r /opt/bootkube/assets/experimental/manifests
|
|
||||||
[ -d /opt/bootkube/assets/experimental/bootstrap-manifests ] && mv /opt/bootkube/assets/experimental/bootstrap-manifests/* /opt/bootkube/assets/bootstrap-manifests && rm -r /opt/bootkube/assets/experimental/bootstrap-manifests
|
|
||||||
BOOTKUBE_ACI="$${BOOTKUBE_ACI:-quay.io/coreos/bootkube}"
|
BOOTKUBE_ACI="$${BOOTKUBE_ACI:-quay.io/coreos/bootkube}"
|
||||||
BOOTKUBE_VERSION="$${BOOTKUBE_VERSION:-v0.6.1}"
|
BOOTKUBE_VERSION="$${BOOTKUBE_VERSION:-v0.9.1}"
|
||||||
BOOTKUBE_ASSETS="$${BOOTKUBE_ASSETS:-/opt/bootkube/assets}"
|
BOOTKUBE_ASSETS="$${BOOTKUBE_ASSETS:-/opt/bootkube/assets}"
|
||||||
exec /usr/bin/rkt run \
|
exec /usr/bin/rkt run \
|
||||||
--trust-keys-from-https \
|
--trust-keys-from-https \
|
||||||
|
@ -5,6 +5,15 @@ systemd:
|
|||||||
enable: true
|
enable: true
|
||||||
- name: locksmithd.service
|
- name: locksmithd.service
|
||||||
mask: true
|
mask: true
|
||||||
|
- name: kubelet.path
|
||||||
|
enable: true
|
||||||
|
contents: |
|
||||||
|
[Unit]
|
||||||
|
Description=Watch for kubeconfig
|
||||||
|
[Path]
|
||||||
|
PathExists=/etc/kubernetes/kubeconfig
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
- name: wait-for-dns.service
|
- name: wait-for-dns.service
|
||||||
enable: true
|
enable: true
|
||||||
contents: |
|
contents: |
|
||||||
@ -19,45 +28,48 @@ systemd:
|
|||||||
[Install]
|
[Install]
|
||||||
RequiredBy=kubelet.service
|
RequiredBy=kubelet.service
|
||||||
- name: kubelet.service
|
- name: kubelet.service
|
||||||
enable: true
|
|
||||||
contents: |
|
contents: |
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Kubelet via Hyperkube ACI
|
Description=Kubelet via Hyperkube ACI
|
||||||
Requires=coreos-metadata.service
|
Requires=coreos-metadata.service
|
||||||
After=coreos-metadata.service
|
After=coreos-metadata.service
|
||||||
|
Wants=rpc-statd.service
|
||||||
[Service]
|
[Service]
|
||||||
EnvironmentFile=/etc/kubernetes/kubelet.env
|
EnvironmentFile=/etc/kubernetes/kubelet.env
|
||||||
EnvironmentFile=/run/metadata/coreos
|
EnvironmentFile=/run/metadata/coreos
|
||||||
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/run/kubelet-pod.uuid \
|
Environment="RKT_RUN_ARGS=--uuid-file-save=/var/cache/kubelet-pod.uuid \
|
||||||
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
--volume=resolv,kind=host,source=/etc/resolv.conf \
|
||||||
--mount volume=resolv,target=/etc/resolv.conf \
|
--mount volume=resolv,target=/etc/resolv.conf \
|
||||||
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
--volume var-lib-cni,kind=host,source=/var/lib/cni \
|
||||||
--mount volume=var-lib-cni,target=/var/lib/cni \
|
--mount volume=var-lib-cni,target=/var/lib/cni \
|
||||||
|
--volume opt-cni-bin,kind=host,source=/opt/cni/bin \
|
||||||
|
--mount volume=opt-cni-bin,target=/opt/cni/bin \
|
||||||
--volume var-log,kind=host,source=/var/log \
|
--volume var-log,kind=host,source=/var/log \
|
||||||
--mount volume=var-log,target=/var/log"
|
--mount volume=var-log,target=/var/log \
|
||||||
|
--insecure-options=image"
|
||||||
|
ExecStartPre=/bin/mkdir -p /opt/cni/bin
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/manifests
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/cni/net.d
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/checkpoint-secrets
|
||||||
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
ExecStartPre=/bin/mkdir -p /etc/kubernetes/inactive-manifests
|
||||||
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
ExecStartPre=/bin/mkdir -p /var/lib/cni
|
||||||
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
ExecStartPre=/usr/bin/bash -c "grep 'certificate-authority-data' /etc/kubernetes/kubeconfig | awk '{print $2}' | base64 -d > /etc/kubernetes/ca.crt"
|
||||||
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/run/kubelet-pod.uuid
|
ExecStartPre=-/usr/bin/rkt rm --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
ExecStart=/usr/lib/coreos/kubelet-wrapper \
|
||||||
--kubeconfig=/etc/kubernetes/kubeconfig \
|
--allow-privileged \
|
||||||
--require-kubeconfig \
|
|
||||||
--client-ca-file=/etc/kubernetes/ca.crt \
|
|
||||||
--anonymous-auth=false \
|
--anonymous-auth=false \
|
||||||
|
--client-ca-file=/etc/kubernetes/ca.crt \
|
||||||
|
--cluster_dns=${k8s_dns_service_ip} \
|
||||||
|
--cluster_domain=${cluster_domain_suffix} \
|
||||||
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
--cni-conf-dir=/etc/kubernetes/cni/net.d \
|
||||||
--network-plugin=cni \
|
|
||||||
--lock-file=/var/run/lock/kubelet.lock \
|
|
||||||
--exit-on-lock-contention \
|
--exit-on-lock-contention \
|
||||||
--hostname-override=$${COREOS_DIGITALOCEAN_IPV4_PRIVATE_0} \
|
--hostname-override=$${COREOS_DIGITALOCEAN_IPV4_PRIVATE_0} \
|
||||||
--pod-manifest-path=/etc/kubernetes/manifests \
|
--kubeconfig=/etc/kubernetes/kubeconfig \
|
||||||
--allow-privileged \
|
--lock-file=/var/run/lock/kubelet.lock \
|
||||||
|
--network-plugin=cni \
|
||||||
--node-labels=node-role.kubernetes.io/node \
|
--node-labels=node-role.kubernetes.io/node \
|
||||||
--cluster_dns=${k8s_dns_service_ip} \
|
--pod-manifest-path=/etc/kubernetes/manifests
|
||||||
--cluster_domain=cluster.local
|
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/cache/kubelet-pod.uuid
|
||||||
ExecStop=-/usr/bin/rkt stop --uuid-file=/var/run/kubelet-pod.uuid
|
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
[Install]
|
[Install]
|
||||||
@ -76,34 +88,13 @@ systemd:
|
|||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
storage:
|
storage:
|
||||||
files:
|
files:
|
||||||
- path: /etc/kubernetes/kubeconfig
|
|
||||||
filesystem: root
|
|
||||||
mode: 0644
|
|
||||||
contents:
|
|
||||||
inline: |
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Config
|
|
||||||
clusters:
|
|
||||||
- name: local
|
|
||||||
cluster:
|
|
||||||
server: ${kubeconfig_server}
|
|
||||||
certificate-authority-data: ${kubeconfig_ca_cert}
|
|
||||||
users:
|
|
||||||
- name: kubelet
|
|
||||||
user:
|
|
||||||
client-certificate-data: ${kubeconfig_kubelet_cert}
|
|
||||||
client-key-data: ${kubeconfig_kubelet_key}
|
|
||||||
contexts:
|
|
||||||
- context:
|
|
||||||
cluster: local
|
|
||||||
user: kubelet
|
|
||||||
- path: /etc/kubernetes/kubelet.env
|
- path: /etc/kubernetes/kubelet.env
|
||||||
filesystem: root
|
filesystem: root
|
||||||
mode: 0644
|
mode: 0644
|
||||||
contents:
|
contents:
|
||||||
inline: |
|
inline: |
|
||||||
KUBELET_IMAGE_URL=quay.io/coreos/hyperkube
|
KUBELET_IMAGE_URL=docker://gcr.io/google_containers/hyperkube
|
||||||
KUBELET_IMAGE_TAG=v1.7.3_coreos.0
|
KUBELET_IMAGE_TAG=v1.8.6
|
||||||
- path: /etc/sysctl.d/max-user-watches.conf
|
- path: /etc/sysctl.d/max-user-watches.conf
|
||||||
filesystem: root
|
filesystem: root
|
||||||
contents:
|
contents:
|
||||||
@ -120,7 +111,8 @@ storage:
|
|||||||
--trust-keys-from-https \
|
--trust-keys-from-https \
|
||||||
--volume config,kind=host,source=/etc/kubernetes \
|
--volume config,kind=host,source=/etc/kubernetes \
|
||||||
--mount volume=config,target=/etc/kubernetes \
|
--mount volume=config,target=/etc/kubernetes \
|
||||||
quay.io/coreos/hyperkube:v1.7.3_coreos.0 \
|
--insecure-options=image \
|
||||||
|
docker://gcr.io/google_containers/hyperkube:v1.8.6 \
|
||||||
--net=host \
|
--net=host \
|
||||||
--dns=host \
|
--dns=host \
|
||||||
--exec=/kubectl -- --kubeconfig=/etc/kubernetes/kubeconfig delete node $(hostname)
|
--exec=/kubectl -- --kubeconfig=/etc/kubernetes/kubeconfig delete node $(hostname)
|
||||||
|
@ -14,6 +14,22 @@ resource "digitalocean_record" "controllers" {
|
|||||||
value = "${element(digitalocean_droplet.controllers.*.ipv4_address, count.index)}"
|
value = "${element(digitalocean_droplet.controllers.*.ipv4_address, count.index)}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Discrete DNS records for each controller's private IPv4 for etcd usage
|
||||||
|
resource "digitalocean_record" "etcds" {
|
||||||
|
count = "${var.controller_count}"
|
||||||
|
|
||||||
|
# DNS zone where record should be created
|
||||||
|
domain = "${var.dns_zone}"
|
||||||
|
|
||||||
|
# DNS record (will be prepended to domain)
|
||||||
|
name = "${var.cluster_name}-etcd${count.index}"
|
||||||
|
type = "A"
|
||||||
|
ttl = 300
|
||||||
|
|
||||||
|
# private IPv4 address for etcd
|
||||||
|
value = "${element(digitalocean_droplet.controllers.*.ipv4_address_private, count.index)}"
|
||||||
|
}
|
||||||
|
|
||||||
# Controller droplet instances
|
# Controller droplet instances
|
||||||
resource "digitalocean_droplet" "controllers" {
|
resource "digitalocean_droplet" "controllers" {
|
||||||
count = "${var.controller_count}"
|
count = "${var.controller_count}"
|
||||||
@ -28,7 +44,7 @@ resource "digitalocean_droplet" "controllers" {
|
|||||||
ipv6 = true
|
ipv6 = true
|
||||||
private_networking = true
|
private_networking = true
|
||||||
|
|
||||||
user_data = "${data.ct_config.controller_ign.rendered}"
|
user_data = "${element(data.ct_config.controller_ign.*.rendered, count.index)}"
|
||||||
ssh_keys = "${var.ssh_fingerprints}"
|
ssh_keys = "${var.ssh_fingerprints}"
|
||||||
|
|
||||||
tags = [
|
tags = [
|
||||||
@ -43,19 +59,35 @@ resource "digitalocean_tag" "controllers" {
|
|||||||
|
|
||||||
# Controller Container Linux Config
|
# Controller Container Linux Config
|
||||||
data "template_file" "controller_config" {
|
data "template_file" "controller_config" {
|
||||||
|
count = "${var.controller_count}"
|
||||||
|
|
||||||
template = "${file("${path.module}/cl/controller.yaml.tmpl")}"
|
template = "${file("${path.module}/cl/controller.yaml.tmpl")}"
|
||||||
|
|
||||||
vars = {
|
vars = {
|
||||||
|
# Cannot use cyclic dependencies on controllers or their DNS records
|
||||||
|
etcd_name = "etcd${count.index}"
|
||||||
|
etcd_domain = "${var.cluster_name}-etcd${count.index}.${var.dns_zone}"
|
||||||
|
|
||||||
|
# etcd0=https://cluster-etcd0.example.com,etcd1=https://cluster-etcd1.example.com,...
|
||||||
|
etcd_initial_cluster = "${join(",", formatlist("%s=https://%s:2380", null_resource.repeat.*.triggers.name, null_resource.repeat.*.triggers.domain))}"
|
||||||
k8s_dns_service_ip = "${cidrhost(var.service_cidr, 10)}"
|
k8s_dns_service_ip = "${cidrhost(var.service_cidr, 10)}"
|
||||||
k8s_etcd_service_ip = "${cidrhost(var.service_cidr, 15)}"
|
cluster_domain_suffix = "${var.cluster_domain_suffix}"
|
||||||
kubeconfig_ca_cert = "${module.bootkube.ca_cert}"
|
}
|
||||||
kubeconfig_kubelet_cert = "${module.bootkube.kubelet_cert}"
|
}
|
||||||
kubeconfig_kubelet_key = "${module.bootkube.kubelet_key}"
|
|
||||||
kubeconfig_server = "${module.bootkube.server}"
|
# Horrible hack to generate a Terraform list of a desired length without dependencies.
|
||||||
|
# Ideal ${repeat("etcd", 3) -> ["etcd", "etcd", "etcd"]}
|
||||||
|
resource null_resource "repeat" {
|
||||||
|
count = "${var.controller_count}"
|
||||||
|
|
||||||
|
triggers {
|
||||||
|
name = "etcd${count.index}"
|
||||||
|
domain = "${var.cluster_name}-etcd${count.index}.${var.dns_zone}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data "ct_config" "controller_ign" {
|
data "ct_config" "controller_ign" {
|
||||||
content = "${data.template_file.controller_config.rendered}"
|
count = "${var.controller_count}"
|
||||||
|
content = "${element(data.template_file.controller_config.*.rendered, count.index)}"
|
||||||
pretty_print = false
|
pretty_print = false
|
||||||
}
|
}
|
||||||
|
25
digital-ocean/container-linux/kubernetes/require.tf
Normal file
25
digital-ocean/container-linux/kubernetes/require.tf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Terraform version and plugin versions
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.10.4"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "digitalocean" {
|
||||||
|
version = "0.1.2"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "local" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "null" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "template" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "tls" {
|
||||||
|
version = "~> 1.0"
|
||||||
|
}
|
@ -1,7 +1,75 @@
|
|||||||
|
# Secure copy kubeconfig to all nodes. Activates kubelet.service
|
||||||
|
resource "null_resource" "copy-secrets" {
|
||||||
|
count = "${var.controller_count + var.worker_count}"
|
||||||
|
|
||||||
|
connection {
|
||||||
|
type = "ssh"
|
||||||
|
host = "${element(concat(digitalocean_droplet.controllers.*.ipv4_address, digitalocean_droplet.workers.*.ipv4_address), count.index)}"
|
||||||
|
user = "core"
|
||||||
|
timeout = "15m"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.kubeconfig}"
|
||||||
|
destination = "$HOME/kubeconfig"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_ca_cert}"
|
||||||
|
destination = "$HOME/etcd-client-ca.crt"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_client_cert}"
|
||||||
|
destination = "$HOME/etcd-client.crt"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_client_key}"
|
||||||
|
destination = "$HOME/etcd-client.key"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_server_cert}"
|
||||||
|
destination = "$HOME/etcd-server.crt"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_server_key}"
|
||||||
|
destination = "$HOME/etcd-server.key"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_peer_cert}"
|
||||||
|
destination = "$HOME/etcd-peer.crt"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "file" {
|
||||||
|
content = "${module.bootkube.etcd_peer_key}"
|
||||||
|
destination = "$HOME/etcd-peer.key"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "remote-exec" {
|
||||||
|
inline = [
|
||||||
|
"sudo mkdir -p /etc/ssl/etcd/etcd",
|
||||||
|
"sudo mv etcd-client* /etc/ssl/etcd/",
|
||||||
|
"sudo cp /etc/ssl/etcd/etcd-client-ca.crt /etc/ssl/etcd/etcd/server-ca.crt",
|
||||||
|
"sudo mv etcd-server.crt /etc/ssl/etcd/etcd/server.crt",
|
||||||
|
"sudo mv etcd-server.key /etc/ssl/etcd/etcd/server.key",
|
||||||
|
"sudo cp /etc/ssl/etcd/etcd-client-ca.crt /etc/ssl/etcd/etcd/peer-ca.crt",
|
||||||
|
"sudo mv etcd-peer.crt /etc/ssl/etcd/etcd/peer.crt",
|
||||||
|
"sudo mv etcd-peer.key /etc/ssl/etcd/etcd/peer.key",
|
||||||
|
"sudo chown -R etcd:etcd /etc/ssl/etcd",
|
||||||
|
"sudo chmod -R 500 /etc/ssl/etcd",
|
||||||
|
"sudo mv /home/core/kubeconfig /etc/kubernetes/kubeconfig",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Secure copy bootkube assets to ONE controller and start bootkube to perform
|
# Secure copy bootkube assets to ONE controller and start bootkube to perform
|
||||||
# one-time self-hosted cluster bootstrapping.
|
# one-time self-hosted cluster bootstrapping.
|
||||||
resource "null_resource" "bootkube-start" {
|
resource "null_resource" "bootkube-start" {
|
||||||
depends_on = ["module.bootkube", "digitalocean_droplet.controllers"]
|
depends_on = ["module.bootkube", "null_resource.copy-secrets"]
|
||||||
|
|
||||||
connection {
|
connection {
|
||||||
type = "ssh"
|
type = "ssh"
|
||||||
|
@ -70,9 +70,16 @@ variable "pod_cidr" {
|
|||||||
variable "service_cidr" {
|
variable "service_cidr" {
|
||||||
description = <<EOD
|
description = <<EOD
|
||||||
CIDR IP range to assign Kubernetes services.
|
CIDR IP range to assign Kubernetes services.
|
||||||
The 1st IP will be reserved for kube_apiserver, the 10th IP will be reserved for kube-dns, the 15th IP will be reserved for self-hosted etcd, and the 200th IP will be reserved for bootstrap self-hosted etcd.
|
The 1st IP will be reserved for kube_apiserver, the 10th IP will be reserved for kube-dns.
|
||||||
EOD
|
EOD
|
||||||
|
|
||||||
type = "string"
|
type = "string"
|
||||||
default = "10.3.0.0/16"
|
default = "10.3.0.0/16"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "cluster_domain_suffix" {
|
||||||
|
description = "Queries for domains with the suffix will be answered by kube-dns. Default is cluster.local (e.g. foo.default.svc.cluster.local) "
|
||||||
|
type = "string"
|
||||||
|
default = "cluster.local"
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -45,10 +45,7 @@ data "template_file" "worker_config" {
|
|||||||
vars = {
|
vars = {
|
||||||
k8s_dns_service_ip = "${cidrhost(var.service_cidr, 10)}"
|
k8s_dns_service_ip = "${cidrhost(var.service_cidr, 10)}"
|
||||||
k8s_etcd_service_ip = "${cidrhost(var.service_cidr, 15)}"
|
k8s_etcd_service_ip = "${cidrhost(var.service_cidr, 15)}"
|
||||||
kubeconfig_ca_cert = "${module.bootkube.ca_cert}"
|
cluster_domain_suffix = "${var.cluster_domain_suffix}"
|
||||||
kubeconfig_kubelet_cert = "${module.bootkube.kubelet_cert}"
|
|
||||||
kubeconfig_kubelet_key = "${module.bootkube.kubelet_key}"
|
|
||||||
kubeconfig_server = "${module.bootkube.server}"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
# Calico Policy
|
|
||||||
|
|
||||||
!!! bug "In Progress"
|
|
||||||
These docs haven't been moved over yet.
|
|
@ -12,13 +12,13 @@ kubectl apply -f addons/cluo -R
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
`update-agent` runs as a DaemonSet and annotates a node when `update-engine.service` indiates an update has been installed and a reboot is needed. It also adds additional labels and annotations to nodes.
|
`update-agent` runs as a DaemonSet and annotates a node when `update-engine.service` indicates an update has been installed and a reboot is needed. It also adds additional labels and annotations to nodes.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ kubectl get nodes --show-labels
|
$ kubectl get nodes --show-labels
|
||||||
...
|
...
|
||||||
container-linux-update.v1.coreos.com/group=stable
|
container-linux-update.v1.coreos.com/group=stable
|
||||||
container-linux-update.v1.coreos.com/version=1465.6.0
|
container-linux-update.v1.coreos.com/version=1576.4.0
|
||||||
```
|
```
|
||||||
|
|
||||||
`update-operator` ensures one node reboots at a time and that pods are drained prior to reboot.
|
`update-operator` ensures one node reboots at a time and that pods are drained prior to reboot.
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
# Kubernetes Dashboard
|
# Kubernetes Dashboard
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
The Kubernetes Dashboard takes [unusual approaches](https://github.com/kubernetes/dashboard/wiki/Access-control#authorization-header) to security and is often a point of security escalations. We recommend you do don't deploy it and get familiar with `kubectl`, if possible.
|
||||||
|
|
||||||
The Kubernetes [Dashboard](https://github.com/kubernetes/dashboard) provides a web UI to manage a Kubernetes cluster for those who prefer an alternative to `kubectl`.
|
The Kubernetes [Dashboard](https://github.com/kubernetes/dashboard) provides a web UI to manage a Kubernetes cluster for those who prefer an alternative to `kubectl`.
|
||||||
|
|
||||||
## Create
|
## Create
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user