Skip to content

Commit 9a1f4f0

Browse files
committed
ci: Cilium watcher deployment
1 parent 3fc8e90 commit 9a1f4f0

File tree

1 file changed

+379
-0
lines changed

1 file changed

+379
-0
lines changed
Lines changed: 379 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,379 @@
1+
2+
apiVersion: v1
3+
kind: ServiceAccount
4+
metadata:
5+
name: cilium-watcher-sa
6+
namespace: kube-system
7+
---
8+
apiVersion: rbac.authorization.k8s.io/v1
9+
kind: Role
10+
metadata:
11+
name: cilium-watcher-role
12+
namespace: kube-system
13+
rules:
14+
- apiGroups: [""]
15+
resources: ["serviceaccounts"]
16+
verbs: ["get", "list", "create", "update", "patch", "apply"]
17+
- apiGroups: ["apps"]
18+
resources: ["daemonsets"]
19+
verbs: ["get", "list", "create", "watch", "patch", "apply"]
20+
---
21+
apiVersion: rbac.authorization.k8s.io/v1
22+
kind: RoleBinding
23+
metadata:
24+
name: cilium-watcher-binding
25+
namespace: kube-system
26+
subjects:
27+
- kind: ServiceAccount
28+
name: cilium-watcher-sa
29+
roleRef:
30+
kind: Role
31+
name: cilium-watcher-role
32+
apiGroup: rbac.authorization.k8s.io
33+
---
34+
### For ClusterRole and ClusterRoleBinding
35+
apiVersion: rbac.authorization.k8s.io/v1
36+
kind: ClusterRole
37+
metadata:
38+
name: cilium-watcher-cluster-role
39+
rules:
40+
- apiGroups: ["rbac.authorization.k8s.io"]
41+
resources: ["clusterroles", "clusterrolebindings"]
42+
verbs: ["get", "list", "create", "update", "patch", "watch"]
43+
- apiGroups:
44+
- networking.k8s.io
45+
resources:
46+
- networkpolicies
47+
verbs:
48+
- get
49+
- list
50+
- watch
51+
- apiGroups:
52+
- discovery.k8s.io
53+
resources:
54+
- endpointslices
55+
verbs:
56+
- get
57+
- list
58+
- watch
59+
- apiGroups:
60+
- ""
61+
resources:
62+
- namespaces
63+
- services
64+
- pods
65+
- endpoints
66+
- nodes
67+
verbs:
68+
- get
69+
- list
70+
- watch
71+
- apiGroups:
72+
- apiextensions.k8s.io
73+
resources:
74+
- customresourcedefinitions
75+
verbs:
76+
- list
77+
- watch
78+
- get
79+
- apiGroups:
80+
- cilium.io
81+
resources:
82+
- ciliumbgppeeringpolicies
83+
- ciliumclusterwideenvoyconfigs
84+
- ciliumclusterwidenetworkpolicies
85+
- ciliumegressgatewaypolicies
86+
- ciliumendpoints
87+
- ciliumendpointslices
88+
- ciliumenvoyconfigs
89+
- ciliumidentities
90+
- ciliumlocalredirectpolicies
91+
- ciliumnetworkpolicies
92+
- ciliumnodes
93+
- ciliumnodeconfigs
94+
- ciliumloadbalancerippools
95+
- ciliumcidrgroups
96+
- ciliuml2announcementpolicies
97+
- ciliumpodippools
98+
- ciliumbgpnodeconfigs
99+
- ciliumbgpadvertisements
100+
- ciliumbgppeerconfigs
101+
verbs:
102+
- list
103+
- watch
104+
- apiGroups:
105+
- cilium.io
106+
resources:
107+
- ciliumidentities
108+
- ciliumendpoints
109+
- ciliumnodes
110+
verbs:
111+
- create
112+
- apiGroups:
113+
- cilium.io
114+
resources:
115+
- ciliumidentities
116+
verbs:
117+
- update
118+
- apiGroups:
119+
- cilium.io
120+
resources:
121+
- ciliumendpoints
122+
verbs:
123+
- delete
124+
- get
125+
- apiGroups:
126+
- cilium.io
127+
resources:
128+
- ciliumnodes
129+
- ciliumnodes/status
130+
verbs:
131+
- get
132+
- update
133+
- apiGroups:
134+
- cilium.io
135+
resources:
136+
- ciliumnetworkpolicies/status
137+
- ciliumclusterwidenetworkpolicies/status
138+
- ciliumendpoints/status
139+
- ciliumendpoints
140+
- ciliuml2announcementpolicies/status
141+
- ciliumbgpnodeconfigs/status
142+
verbs:
143+
- patch
144+
- apiGroups:
145+
- ""
146+
resources:
147+
- events
148+
verbs:
149+
- create
150+
- apiGroups:
151+
- cilium.io
152+
resources:
153+
- ciliumnodes
154+
verbs:
155+
- patch
156+
157+
---
158+
### For ClusterRole and ClusterRoleBinding
159+
apiVersion: rbac.authorization.k8s.io/v1
160+
kind: ClusterRoleBinding
161+
metadata:
162+
name: cilium-watcher-cluster-binding
163+
subjects:
164+
- kind: ServiceAccount
165+
name: cilium-watcher-sa
166+
namespace: kube-system
167+
roleRef:
168+
kind: ClusterRole
169+
name: cilium-watcher-cluster-role
170+
apiGroup: rbac.authorization.k8s.io
171+
---
172+
apiVersion: apps/v1
173+
kind: Deployment
174+
metadata:
175+
name: cilium-watcher
176+
namespace: kube-system
177+
spec:
178+
replicas: 1
179+
selector:
180+
matchLabels:
181+
app: cilium-watcher
182+
template:
183+
metadata:
184+
labels:
185+
app: cilium-watcher
186+
spec:
187+
affinity:
188+
nodeAffinity:
189+
requiredDuringSchedulingIgnoredDuringExecution:
190+
nodeSelectorTerms:
191+
- matchExpressions:
192+
- key: kubernetes.azure.com/managed
193+
# set on unmanaged nodes
194+
operator: NotIn
195+
values:
196+
- "false"
197+
hostNetwork: true
198+
serviceAccountName: cilium-watcher-sa
199+
containers:
200+
- name: ds-watcher
201+
image: bitnami/kubectl:latest
202+
command:
203+
- /bin/sh
204+
- -c
205+
- |
206+
207+
NAMESPACE="kube-system"
208+
export ORIGINAL_DAEMONSET="cilium"
209+
export MODIFIED_DAEMONSET="cilium-unmanaged"
210+
211+
update_daemonset() {
212+
local temp_file="/tmp/${ORIGINAL_DAEMONSET}_daemonset.yaml"
213+
214+
echo "Fetching the latest Cilium DaemonSet YAML..."
215+
kubectl get daemonset $ORIGINAL_DAEMONSET -n $NAMESPACE -oyaml > "$temp_file"
216+
217+
echo "Modifying the YAML..."
218+
# Change the name of the DaemonSet
219+
yq eval '.metadata.name = strenv(MODIFIED_DAEMONSET)' -i "$temp_file"
220+
221+
yq eval 'del(.metadata.annotations)' -i "$temp_file"
222+
yq eval 'del(.metadata.labels)' -i "$temp_file"
223+
224+
# Remove metadata.annotations and metadata.labels.app.kubernetes.io/managed-by
225+
yq eval 'del(.spec.template.metadata.annotations)' -i "$temp_file"
226+
yq eval 'del(.spec.template.metadata.labels."kubernetes.azure.com/managedby")' -i "$temp_file"
227+
yq eval '.spec.template.metadata.labels."k8s-app" = strenv(MODIFIED_DAEMONSET)' -i "$temp_file"
228+
yq eval '.spec.selector.matchLabels."k8s-app" = strenv(MODIFIED_DAEMONSET)' -i "$temp_file"
229+
230+
# yq eval '.spec.template.spec.containers[0].args += ["--enable-bandwidth-manager"]' -i "$temp_file"
231+
yq eval '.spec.template.spec.containers[0].args += ["--cni-chaining-mode=generic-veth"]' -i "$temp_file"
232+
# yq eval '.spec.template.spec.containers[0].args += ["--enable-host-legacy-routing=false"]' -i "$temp_file"
233+
234+
### TODO / TESTING
235+
# Remove if present
236+
# yq eval 'del(.spec.template.spec.containers[0].args[] | select(. == "--kube-proxy-replacement=probe"))' -i "$temp_file"
237+
# kube-proxy-replacement-healthz-bind-address: "0.0.0.0:10256"
238+
#
239+
240+
241+
# Replace service account name
242+
yq eval '.spec.template.spec.serviceAccountName = strenv(MODIFIED_DAEMONSET)' -i "$temp_file"
243+
yq eval '.spec.template.spec.serviceAccount = strenv(MODIFIED_DAEMONSET)' -i "$temp_file"
244+
245+
# Replace node affinity requirement
246+
yq eval 'del(.spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[].matchExpressions[] | select(.key == "kubernetes.azure.com/ebpf-dataplane"))' -i "$temp_file"
247+
yq eval 'with(.spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[]; .matchExpressions |= map(select(.key != "kubernetes.azure.com/cluster")) | .matchExpressions += {"key": "kubernetes.azure.com/managed", "operator": "In", "values": ["false"]})' -i "$temp_file"
248+
249+
# Remove status section
250+
yq eval 'del(.status)' -i "$temp_file"
251+
252+
# Ensure no duplicate conflicts
253+
yq eval 'del(.metadata.resourceVersion)' -i "$temp_file"
254+
yq eval 'del(.metadata.uid)' -i "$temp_file"
255+
256+
echo "Applying the modified DaemonSet..."
257+
cat "$temp_file"
258+
kubectl apply -f "$temp_file"
259+
echo "Cilium Unmanaged DaemonSet updated!"
260+
}
261+
262+
kubectl get daemonset $ORIGINAL_DAEMONSET -n $NAMESPACE -w | while read -r line; do
263+
if echo "$line" | grep -q "$ORIGINAL_DAEMONSET"; then
264+
echo "Detected change in $ORIGINAL_DAEMONSET, updating..."
265+
update_daemonset
266+
fi
267+
done
268+
269+
- name: rbac-watcher
270+
image: bitnami/kubectl:latest
271+
command:
272+
- /bin/sh
273+
- -c
274+
- |
275+
276+
NAMESPACE="kube-system"
277+
export ORIGINAL_DAEMONSET="cilium"
278+
export MODIFIED_DAEMONSET="cilium-unmanaged"
279+
update_rbac() {
280+
local sa_file="/tmp/${ORIGINAL_DAEMONSET}_sa.yaml"
281+
local cr_file="/tmp/${ORIGINAL_DAEMONSET}_cr.yaml"
282+
local crb_file="/tmp/${ORIGINAL_DAEMONSET}_crb.yaml"
283+
local current_file=""
284+
285+
# --- ClusterRole ---
286+
current_file=$cr_file
287+
echo "Fetching the latest Cilium ClusterRole YAML..."
288+
kubectl get clusterrole $ORIGINAL_DAEMONSET -oyaml > "$current_file"
289+
290+
echo "Modifying the ClusterRole YAML..."
291+
# Change name
292+
yq eval '.metadata.name = strenv(MODIFIED_DAEMONSET)' -i "$current_file"
293+
294+
# Remove metadata.annotations
295+
yq eval 'del(.metadata.annotations)' -i "$current_file"
296+
yq eval 'del(.metadata.labels."app.kubernetes.io/managed-by")' -i "$current_file"
297+
yq eval 'del(.metadata.labels."app.kubernetes.io/actually-managed-by")' -i "$current_file"
298+
yq eval '.metadata.labels."app.kubernetes.io/part-of" = strenv(MODIFIED_DAEMONSET)' -i "$current_file"
299+
300+
# Ensure no duplicate conflicts
301+
yq eval 'del(.metadata.resourceVersion)' -i "$current_file"
302+
yq eval 'del(.metadata.uid)' -i "$current_file"
303+
yq eval 'del(.metadata.creationTimestamp)' -i "$current_file"
304+
305+
echo "Applying the modified ClusterRole..."
306+
cat "$current_file"
307+
kubectl apply -f "$current_file"
308+
echo "Cilium Unmanaged ClusterRole updated!"
309+
310+
311+
# --- ServiceAccount ---
312+
if kubectl get serviceaccount -n $NAMESPACE $MODIFIED_DAEMONSET -oyaml &> /dev/null; then
313+
echo "ServiceAccount $MODIFIED_DAEMONSET already exists. Skipping creation."
314+
else
315+
current_file=$sa_file
316+
echo "Fetching the latest Cilium ServiceAccount YAML..."
317+
kubectl get serviceaccount -n $NAMESPACE $ORIGINAL_DAEMONSET -oyaml > "$current_file"
318+
319+
echo "Modifying the ServiceAccount YAML..."
320+
# Change name
321+
yq eval '.metadata.name = strenv(MODIFIED_DAEMONSET)' -i "$current_file"
322+
323+
# Remove metadata.annotations
324+
yq eval 'del(.metadata.annotations)' -i "$current_file"
325+
yq eval 'del(.metadata.labels)' -i "$current_file"
326+
yq eval 'del(.metadata.labels."app.kubernetes.io/actually-managed-by")' -i "$current_file"
327+
328+
# Ensure no duplicate conflicts
329+
yq eval 'del(.metadata.resourceVersion)' -i "$current_file"
330+
yq eval 'del(.metadata.uid)' -i "$current_file"
331+
yq eval 'del(.metadata.creationTimestamp)' -i "$current_file"
332+
333+
echo "Applying the modified ServiceAccount..."
334+
cat "$current_file"
335+
kubectl apply -f "$current_file"
336+
echo "Cilium Unmanaged ServiceAccount updated!"
337+
fi
338+
339+
# --- ClusterRoleBinding ---
340+
if kubectl get clusterrolebinding $MODIFIED_DAEMONSET -oyaml &> /dev/null; then
341+
echo "ClusterRoleBinding $MODIFIED_DAEMONSET already exists. Skipping creation."
342+
else
343+
current_file=$crb_file
344+
echo "Fetching the latest Cilium ClusterRoleBinding YAML..."
345+
kubectl get clusterrolebinding -n $NAMESPACE $ORIGINAL_DAEMONSET -oyaml > "$current_file"
346+
347+
echo "Modifying the ClusterRoleBinding YAML..."
348+
# Change name
349+
yq eval '.metadata.name = strenv(MODIFIED_DAEMONSET)' -i "$current_file"
350+
yq eval '.roleRef.name = strenv(MODIFIED_DAEMONSET)' -i "$current_file"
351+
yq eval '.subjects[0].name = strenv(MODIFIED_DAEMONSET)' -i "$current_file"
352+
353+
# Remove metadata.annotations
354+
yq eval 'del(.metadata.annotations)' -i "$current_file"
355+
yq eval 'del(.metadata.labels."app.kubernetes.io/managed-by")' -i "$current_file"
356+
yq eval 'del(.metadata.labels."app.kubernetes.io/actually-managed-by")' -i "$current_file"
357+
yq eval '.metadata.labels."app.kubernetes.io/part-of" = strenv(MODIFIED_DAEMONSET)' -i "$current_file"
358+
359+
# Ensure no duplicate conflicts
360+
yq eval 'del(.metadata.resourceVersion)' -i "$current_file"
361+
yq eval 'del(.metadata.uid)' -i "$current_file"
362+
yq eval 'del(.metadata.creationTimestamp)' -i "$current_file"
363+
364+
echo "Applying the modified ClusterRoleBinding..."
365+
cat "$current_file"
366+
kubectl apply -f "$current_file"
367+
echo "Cilium Unmanaged ClusterRoleBinding updated!"
368+
fi
369+
370+
371+
}
372+
373+
# DaemonSet RBAC watcher
374+
kubectl get clusterrole $ORIGINAL_DAEMONSET -w | while read -r line; do
375+
if echo "$line" | grep -q "$ORIGINAL_DAEMONSET"; then
376+
echo "Detected change in ClusterRole $ORIGINAL_DAEMONSET, updating RBAC..."
377+
update_rbac
378+
fi
379+
done

0 commit comments

Comments
 (0)