blob: ad58964a9e0ec9c153eece77b732b6a7c437150e [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,
Serge Bazanskic33ebcc2019-11-01 18:43:45 +010028 version:: "v0.8.3",
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +020029 imageController: "metallb/controller:" + cfg.version,
Serge Bazanskic33ebcc2019-11-01 18:43:45 +010030 //imageSpeaker: "metallb/speaker:" + cfg.version,
31 imageSpeaker: "derq3k/metallb-speaker:20191101-180123",
Sergiusz Bazanski14cbacb2019-04-01 18:00:44 +020032 addressPools: error "addressPools must be set in config",
Sergiusz Bazanski1e565dc2019-01-18 09:40:59 +010033 },
34
35 ns: if cfg.namespaceCreate then kube.Namespace(cfg.namespace),
36
Sergiusz Bazanskib13b7ff2019-08-29 20:12:24 +020037 insecurePolicy: policies.AllowNamespaceInsecure(cfg.namespace),
38
Sergiusz Bazanski1e565dc2019-01-18 09:40:59 +010039 saController: kube.ServiceAccount("controller") {
40 metadata+: {
41 namespace: cfg.namespace,
42 },
43 },
44
45 saSpeaker: kube.ServiceAccount("speaker") {
46 metadata+: {
47 namespace: cfg.namespace,
48 },
49 },
50
51 crController: kube.ClusterRole("%s:controller" % cfg.namespace) {
52 rules: [
53 {
54 apiGroups: [""],
55 resources: ["services"],
56 verbs: ["get", "list", "watch", "update"],
57 },
58 {
59 apiGroups: [""],
60 resources: ["services/status"],
61 verbs: ["update"],
62 },
63 {
64 apiGroups: [""],
65 resources: ["events"],
66 verbs: ["create", "patch"],
67 },
68 ],
69 },
70
71 crbController: bindServiceAccountClusterRole(env.saController, env.crController),
72
73 crSpeaker: kube.ClusterRole("%s:speaker" % cfg.namespace) {
74 rules: [
75 {
76 apiGroups: [""],
77 resources: ["services", "endpoints", "nodes"],
78 verbs: ["get", "list", "watch"],
79 },
Serge Bazanskic33ebcc2019-11-01 18:43:45 +010080 {
81 apiGroups: [""],
82 resources: ["events"],
83 verbs: ["create", "patch"],
84 },
Sergiusz Bazanski1e565dc2019-01-18 09:40:59 +010085 ],
86 },
87
88 crbSpeaker: bindServiceAccountClusterRole(env.saSpeaker, env.crSpeaker),
89
90 roleWatcher: kube.Role("config-watcher") {
91 metadata+: {
92 namespace: cfg.namespace,
93 },
94 rules: [
95 {
96 apiGroups: [""],
97 resources: ["configmaps"],
98 verbs: ["get", "list", "watch"],
99 },
100 {
101 apiGroups: [""],
102 resources: ["events"],
103 verbs: ["create"],
104 },
105 ],
106 },
107
108 rbWatcher: kube.RoleBinding("config-watcher") {
109 metadata+: {
110 namespace: cfg.namespace,
111 },
112 subjects: [
113 { kind: "ServiceAccount", name: env.saController.metadata.name },
114 { kind: "ServiceAccount", name: env.saSpeaker.metadata.name },
115 ],
116 roleRef: {
117 apiGroup: "rbac.authorization.k8s.io",
118 kind: "Role",
119 name: env.roleWatcher.metadata.name,
120 },
121 },
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +0200122
123 deployController: kube.Deployment("controller") {
124 metadata+: {
125 namespace: cfg.namespace,
126 },
127 spec+: {
128 revisionHistoryLimit: 3,
129 template+: {
130 spec+: {
131 serviceAccountName: env.saController.metadata.name,
132 terminationGracePeriodSeconds: 0,
133 securityContext: {
134 runAsNonRoot: true,
135 runAsUser: 65534, # nobody
136 },
137 containers_: {
138 controller: kube.Container("controller") {
139 image: cfg.imageController,
140 args: [ "--port=7472", "--config=config" ],
141 ports: [
142 { name: "monitoring", containerPort: 7472 },
143 ],
144 resources: {
Sergiusz Bazanski242152f2019-04-04 16:53:27 +0200145 limits: { cpu: "200m", memory: "300Mi" },
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +0200146 },
147 securityContext: {
148 allowPrivilegeEscalation: false,
149 capabilities: { drop: [ "all" ] },
150 readOnlyRootFilesystem: true,
151 },
152 },
153 },
154 },
155 },
156 },
157 },
158
159 daemonsetSpeaker: kube.DaemonSet("speaker") {
160 metadata+: {
161 namespace: cfg.namespace,
162 },
163 spec+: {
164 template+: {
165 spec+: {
166 serviceAccountName: env.saSpeaker.metadata.name,
167 hostNetwork: true,
168 containers_: {
169 speaker: kube.Container("speaker") {
170 image: cfg.imageSpeaker,
171 args: [ "--port=7472", "--config=config" ],
172 env_: {
173 METALLB_NODE_NAME: kube.FieldRef("spec.nodeName"),
Serge Bazanskic33ebcc2019-11-01 18:43:45 +0100174 METALLB_HOST: kube.FieldRef("status.hostIP"),
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +0200175 },
176 ports: [
177 { name: "monitoring", containerPort: 7472 },
178 ],
179 resources: {
Sergiusz Bazanski242152f2019-04-04 16:53:27 +0200180 limits: { cpu: "200m", memory: "300Mi" },
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +0200181 },
182 securityContext: {
183 allowPrivilegeEscalation: false,
Serge Bazanskic33ebcc2019-11-01 18:43:45 +0100184 capabilities: { drop: [ "all" ], add: [ "NET_ADMIN", "NET_RAW", "SYS_ADMIN" ] },
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +0200185 readOnlyRootFilesystem: true,
186 },
187 },
188 },
189 },
190 },
191 },
192 },
193
194 configMap: kube.ConfigMap("config") {
195 local cm = self,
196 metadata+: {
197 namespace: cfg.namespace,
198 },
199 data: {
200 config: std.manifestYamlDoc({
Sergiusz Bazanski14cbacb2019-04-01 18:00:44 +0200201 "address-pools": cfg.addressPools,
Serge Bazanskic33ebcc2019-11-01 18:43:45 +0100202 "peers": cfg.peers,
Sergiusz Bazanskia9c7e862019-04-01 17:56:28 +0200203 }),
204 },
205 },
Sergiusz Bazanski1e565dc2019-01-18 09:40:59 +0100206 },
207}