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