blob: 7f3d746879b146dd789a0aead16b08985757145b [file] [log] [blame]
Sergiusz Bazanski1e565dc2019-01-18 09:40:59 +01001# Deploy MetalLB
2
3local kube = import "../../../kube/kube.libsonnet";
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +02004local policies = import "../../../kube/policies.libsonnet";
Sergiusz Bazanski1e565dc2019-01-18 09:40:59 +01005
6local bindServiceAccountClusterRole(sa, cr) = kube.ClusterRoleBinding(cr.metadata.name) {
7 roleRef: {
8 apiGroup: "rbac.authorization.k8s.io",
9 kind: "ClusterRole",
10 name: cr.metadata.name,
11 },
12 subjects: [
13 {
14 kind: "ServiceAccount",
15 name: sa.metadata.name,
16 namespace: sa.metadata.namespace,
17 },
18 ],
19};
20
21{
22 Environment: {
23 local env = self,
24 local cfg = env.cfg,
25 cfg:: {
26 namespace: "metallb-system",
27 namespaceCreate: true,
Piotr Dobrowolskib187bf52019-05-05 12:11:14 +020028 version:: "v0.7.3",
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +020029 imageController: "metallb/controller:" + cfg.version,
30 imageSpeaker: "metallb/speaker:" + cfg.version,
Sergiusz Bazanski14cbacb2019-04-01 18:00:44 +020031 addressPools: error "addressPools must be set in config",
Sergiusz Bazanski1e565dc2019-01-18 09:40:59 +010032 },
33
34 ns: if cfg.namespaceCreate then kube.Namespace(cfg.namespace),
35
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +020036 insecurePolicy: policies.AllowNamespaceInsecure(cfg.namespace),
37
Sergiusz Bazanski1e565dc2019-01-18 09:40:59 +010038 saController: kube.ServiceAccount("controller") {
39 metadata+: {
40 namespace: cfg.namespace,
41 },
42 },
43
44 saSpeaker: kube.ServiceAccount("speaker") {
45 metadata+: {
46 namespace: cfg.namespace,
47 },
48 },
49
50 crController: kube.ClusterRole("%s:controller" % cfg.namespace) {
51 rules: [
52 {
53 apiGroups: [""],
54 resources: ["services"],
55 verbs: ["get", "list", "watch", "update"],
56 },
57 {
58 apiGroups: [""],
59 resources: ["services/status"],
60 verbs: ["update"],
61 },
62 {
63 apiGroups: [""],
64 resources: ["events"],
65 verbs: ["create", "patch"],
66 },
67 ],
68 },
69
70 crbController: bindServiceAccountClusterRole(env.saController, env.crController),
71
72 crSpeaker: kube.ClusterRole("%s:speaker" % cfg.namespace) {
73 rules: [
74 {
75 apiGroups: [""],
76 resources: ["services", "endpoints", "nodes"],
77 verbs: ["get", "list", "watch"],
78 },
79 ],
80 },
81
82 crbSpeaker: bindServiceAccountClusterRole(env.saSpeaker, env.crSpeaker),
83
84 roleWatcher: kube.Role("config-watcher") {
85 metadata+: {
86 namespace: cfg.namespace,
87 },
88 rules: [
89 {
90 apiGroups: [""],
91 resources: ["configmaps"],
92 verbs: ["get", "list", "watch"],
93 },
94 {
95 apiGroups: [""],
96 resources: ["events"],
97 verbs: ["create"],
98 },
99 ],
100 },
101
102 rbWatcher: kube.RoleBinding("config-watcher") {
103 metadata+: {
104 namespace: cfg.namespace,
105 },
106 subjects: [
107 { kind: "ServiceAccount", name: env.saController.metadata.name },
108 { kind: "ServiceAccount", name: env.saSpeaker.metadata.name },
109 ],
110 roleRef: {
111 apiGroup: "rbac.authorization.k8s.io",
112 kind: "Role",
113 name: env.roleWatcher.metadata.name,
114 },
115 },
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +0200116
117 deployController: kube.Deployment("controller") {
118 metadata+: {
119 namespace: cfg.namespace,
120 },
121 spec+: {
122 revisionHistoryLimit: 3,
123 template+: {
124 spec+: {
125 serviceAccountName: env.saController.metadata.name,
126 terminationGracePeriodSeconds: 0,
127 securityContext: {
128 runAsNonRoot: true,
129 runAsUser: 65534, # nobody
130 },
131 containers_: {
132 controller: kube.Container("controller") {
133 image: cfg.imageController,
134 args: [ "--port=7472", "--config=config" ],
135 ports: [
136 { name: "monitoring", containerPort: 7472 },
137 ],
138 resources: {
Sergiusz Bazanski242152f2019-04-04 16:53:27 +0200139 limits: { cpu: "200m", memory: "300Mi" },
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +0200140 },
141 securityContext: {
142 allowPrivilegeEscalation: false,
143 capabilities: { drop: [ "all" ] },
144 readOnlyRootFilesystem: true,
145 },
146 },
147 },
148 },
149 },
150 },
151 },
152
153 daemonsetSpeaker: kube.DaemonSet("speaker") {
154 metadata+: {
155 namespace: cfg.namespace,
156 },
157 spec+: {
158 template+: {
159 spec+: {
160 serviceAccountName: env.saSpeaker.metadata.name,
161 hostNetwork: true,
162 containers_: {
163 speaker: kube.Container("speaker") {
164 image: cfg.imageSpeaker,
165 args: [ "--port=7472", "--config=config" ],
166 env_: {
167 METALLB_NODE_NAME: kube.FieldRef("spec.nodeName"),
168 },
169 ports: [
170 { name: "monitoring", containerPort: 7472 },
171 ],
172 resources: {
Sergiusz Bazanski242152f2019-04-04 16:53:27 +0200173 limits: { cpu: "200m", memory: "300Mi" },
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +0200174 },
175 securityContext: {
176 allowPrivilegeEscalation: false,
177 capabilities: { drop: [ "all" ], add: [ "net_raw" ] },
178 readOnlyRootFilesystem: true,
179 },
180 },
181 },
182 },
183 },
184 },
185 },
186
187 configMap: kube.ConfigMap("config") {
188 local cm = self,
189 metadata+: {
190 namespace: cfg.namespace,
191 },
192 data: {
193 config: std.manifestYamlDoc({
Sergiusz Bazanski14cbacb2019-04-01 18:00:44 +0200194 "address-pools": cfg.addressPools,
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +0200195 }),
196 },
197 },
Sergiusz Bazanski1e565dc2019-01-18 09:40:59 +0100198 },
199}