Skip to content

Commit a5ab36a

Browse files
Feature: Add Istio Ambient Mode Support via Overlay Method (#3246)
* feature: ambient with overlay method Signed-off-by: madmecodes <[email protected]> * update: remove empty line minor formatting issue Signed-off-by: madmecodes <[email protected]> * update: remove duplication and use inheritance for gke overlay in ambient Signed-off-by: madmecodes <[email protected]> * update: remove common env variables already in base Signed-off-by: madmecodes <[email protected]> * feat: using components approach to enable ambient-mode and gke specific ambient-gke Signed-off-by: madmecodes <[email protected]> * added ambient workflow to test in kind cluster Signed-off-by: madmecodes <[email protected]> * feat: add Istio Ambient Mode with PSS baseline requirement Signed-off-by: madmecodes <[email protected]> * update: ambient pss upgraded to privilidged Signed-off-by: madmecodes <[email protected]> * upate: cni ztunnel connection debug Signed-off-by: madmecodes <[email protected]> * fix: enable ambient mode in CNI Signed-off-by: madmecodes <[email protected]> * fix: workflow updates from baseline to privilidged Signed-off-by: madmecodes <[email protected]> * fix: ambient netns mount, rbac fix Signed-off-by: madmecodes <[email protected]> * fix: ambient netns mount, rbac fix2 Signed-off-by: madmecodes <[email protected]> * fix: remove duplication for ambient-oauth2-proxy Signed-off-by: madmecodes <[email protected]> * update: workflow added in matrix Signed-off-by: madmecodes <[email protected]> * fix: workflow matrix fix order Signed-off-by: madmecodes <[email protected]> * update: gke-cni component created and remove duplicacy Signed-off-by: madmecodes <[email protected]> * fix: corrected file name from baseline to privileged Signed-off-by: madmecodes <[email protected]> * fix: remove unwanted echo Signed-off-by: madmecodes <[email protected]> * Update common/istio/README.md Signed-off-by: Julius von Kohout <[email protected]> * Delete common/istio/istio-install/components/ambient-mode/istio-namespace-pss-privilege.yaml Signed-off-by: Julius von Kohout <[email protected]> * Update common/istio/README.md Signed-off-by: Julius von Kohout <[email protected]> * Update kustomization.yaml Signed-off-by: Julius von Kohout <[email protected]> --------- Signed-off-by: madmecodes <[email protected]> Signed-off-by: Julius von Kohout <[email protected]> Co-authored-by: Julius von Kohout <[email protected]>
1 parent a6ba19f commit a5ab36a

22 files changed

+477
-42
lines changed

.github/workflows/istio_validation.yaml

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
name: Test Istio CNI and Non-CNI Installation
1+
name: Test Istio Installation Modes (CNI, Insecure, Ambient)
22

33
on:
44
pull_request:
55
paths:
66
- tests/install_KinD_create_KinD_cluster_install_kustomize.sh
77
- tests/istio*
8-
- .github/workflows/istio_cni_test.yaml
8+
- tests/ambient*
9+
- .github/workflows/istio_validation.yaml
910
- common/istio/**
1011
- common/cert-manager/**
1112

@@ -21,7 +22,7 @@ jobs:
2122
runs-on: ubuntu-latest
2223
strategy:
2324
matrix:
24-
istio-mode: ['cni', 'insecure']
25+
istio-mode: ['cni', 'insecure', 'ambient']
2526

2627
steps:
2728
- name: Checkout
@@ -61,6 +62,14 @@ jobs:
6162
kubectl patch validatingwebhookconfiguration istio-validator-istio-system --type='json' \
6263
-p="[{'op': 'add', 'path': '/webhooks/0/clientConfig/caBundle', 'value':'$CA_BUNDLE'}]"
6364
65+
- name: Install Istio Ambient Mode
66+
if: matrix.istio-mode == 'ambient'
67+
run: |
68+
kustomize build common/istio/istio-crds/base | kubectl apply -f -
69+
kustomize build common/istio/istio-namespace/base | kubectl apply -f -
70+
kustomize build common/istio/istio-install/overlays/ambient | kubectl apply -f -
71+
kubectl wait --for=condition=Ready pods --all -n istio-system --timeout 300s
72+
6473
- name: Wait for Istio deployment
6574
run: |
6675
kubectl wait --for=condition=available --timeout=300s deployment/istiod -n istio-system
@@ -92,6 +101,30 @@ jobs:
92101
(echo "ERROR: pilot.cni.enabled should be false in configmap values" && \
93102
kubectl get configmap istio-sidecar-injector -n istio-system -o jsonpath='{.data.values}' && exit 1)
94103
104+
- name: Verify Ambient Mode Installation
105+
if: matrix.istio-mode == 'ambient'
106+
run: |
107+
kubectl get daemonset ztunnel -n istio-system
108+
kubectl rollout status daemonset/ztunnel -n istio-system --timeout=120s
109+
110+
PILOT_ENABLE_AMBIENT=$(kubectl get deployment istiod -n istio-system -o jsonpath='{.spec.template.spec.containers[0].env[?(@.name=="PILOT_ENABLE_AMBIENT")].value}')
111+
if [ "$PILOT_ENABLE_AMBIENT" != "true" ]; then
112+
echo "ERROR: PILOT_ENABLE_AMBIENT should be true, got: $PILOT_ENABLE_AMBIENT"
113+
exit 1
114+
fi
115+
echo "Ambient mode enabled in istiod"
116+
117+
kubectl get daemonset istio-cni-node -n kube-system
118+
kubectl rollout status daemonset/istio-cni-node -n kube-system --timeout=120s
119+
echo "CNI installed for ambient mode"
120+
121+
PSS_LEVEL=$(kubectl get namespace istio-system -o jsonpath='{.metadata.labels.pod-security\.kubernetes\.io/enforce}')
122+
if [ "$PSS_LEVEL" != "privileged" ]; then
123+
echo "ERROR: istio-system should have PSS privileged, got: $PSS_LEVEL"
124+
exit 1
125+
fi
126+
echo "PSS privileged verified for istio-system"
127+
95128
- name: Install OAuth2 Proxy
96129
run: ./tests/oauth2-proxy_install.sh
97130

@@ -104,6 +137,12 @@ jobs:
104137
- name: Create KF Profile
105138
run: ./tests/kubeflow_profile_install.sh
106139

140+
- name: Enable ambient mode for user namespace
141+
if: matrix.istio-mode == 'ambient'
142+
run: |
143+
kubectl label namespace $KF_PROFILE istio-injection- --overwrite
144+
kubectl label namespace $KF_PROFILE istio.io/dataplane-mode=ambient --overwrite
145+
107146
- name: Enable Istio injection and adjust PSS for insecure mode
108147
run: |
109148
@@ -133,14 +172,13 @@ jobs:
133172
EOF
134173
135174
- name: Test sidecar injection
175+
if: matrix.istio-mode != 'ambient'
136176
run: |
137177
kubectl apply -f ./tests/istio_dummy_deployment.yaml -n $KF_PROFILE
138178
kubectl wait --for=condition=available --timeout=160s deployment/test-application -n $KF_PROFILE
139179
140-
# Check for istio-proxy sidecar container injection
141180
POD_NAME=$(kubectl get pods -n $KF_PROFILE -l app=test-application -o jsonpath='{.items[0].metadata.name}')
142181
143-
# Check if istio-proxy container exists (either as sidecar or init container)
144182
ISTIO_PROXY_EXISTS=$(kubectl get pod $POD_NAME -n $KF_PROFILE -o jsonpath='{.spec.containers[*].name}' | grep -c "istio-proxy" || echo "0")
145183
ISTIO_INIT_EXISTS=$(kubectl get pod $POD_NAME -n $KF_PROFILE -o jsonpath='{.spec.initContainers[*].name}' | grep -c "istio-proxy" || echo "0")
146184
@@ -150,12 +188,38 @@ jobs:
150188
kubectl get namespace $KF_PROFILE --show-labels
151189
exit 1
152190
fi
153-
echo "Sidecar injection successful"
154191
155192
# Verify Envoy proxy is responding
156193
kubectl exec -n $KF_PROFILE deployment/test-application -c istio-proxy -- curl -s localhost:15000/ready | grep -q "LIVE" || \
157194
(echo "ERROR: Envoy proxy not responding" && exit 1)
158-
echo "Envoy proxy is healthy"
195+
196+
- name: Test ambient mode (no sidecar)
197+
if: matrix.istio-mode == 'ambient'
198+
run: |
199+
kubectl apply -f ./tests/istio_dummy_deployment.yaml -n $KF_PROFILE
200+
kubectl wait --for=condition=available --timeout=160s deployment/test-application -n $KF_PROFILE
201+
202+
POD_NAME=$(kubectl get pods -n $KF_PROFILE -l app=test-application -o jsonpath='{.items[0].metadata.name}')
203+
204+
CONTAINER_COUNT=$(kubectl get pod $POD_NAME -n $KF_PROFILE -o jsonpath='{.spec.containers[*].name}' | wc -w)
205+
if [ "$CONTAINER_COUNT" -ne "1" ]; then
206+
echo "ERROR: Pod should have only 1 container in ambient mode, found: $CONTAINER_COUNT"
207+
kubectl get pod $POD_NAME -n $KF_PROFILE -o jsonpath='{.spec.containers[*].name}'
208+
exit 1
209+
fi
210+
211+
AMBIENT_LABEL=$(kubectl get namespace $KF_PROFILE -o jsonpath='{.metadata.labels.istio\.io/dataplane-mode}')
212+
if [ "$AMBIENT_LABEL" != "ambient" ]; then
213+
echo "ERROR: Namespace should have istio.io/dataplane-mode=ambient label"
214+
exit 1
215+
fi
216+
217+
- name: Verify ztunnel logs show traffic handling
218+
if: matrix.istio-mode == 'ambient'
219+
run: |
220+
# Check ztunnel logs for workload processing
221+
kubectl logs -n istio-system daemonset/ztunnel --tail=50 | grep -i "workload\|connection\|proxy" || echo "Ztunnel logs (last 50 lines):"
222+
kubectl logs -n istio-system daemonset/ztunnel --tail=50
159223
160224
- name: Test CNI-specific functionality
161225
if: matrix.istio-mode == 'cni'
@@ -179,8 +243,6 @@ jobs:
179243
exit 1
180244
fi
181245
182-
echo "Non-CNI verification successful: found istio-init, no istio-validation"
183-
184246
- name: Port-forward the istio-ingress gateway
185247
run: ./tests/port_forward_gateway.sh
186248

@@ -194,6 +256,13 @@ jobs:
194256
if: matrix.istio-mode == 'cni'
195257
run: ./tests/PSS_enable.sh
196258

259+
- name: Apply Pod Security Standards Restricted to user namespace (ambient mode)
260+
if: matrix.istio-mode == 'ambient'
261+
run: |
262+
# Apply PSS restricted to user namespace (ztunnel runs in istio-system, not user namespaces)
263+
kubectl label namespace $KF_PROFILE pod-security.kubernetes.io/enforce=restricted --overwrite
264+
kubectl label namespace $KF_PROFILE pod-security.kubernetes.io/enforce-version=latest --overwrite
265+
197266
- name: Collect debug information on failure
198267
if: failure()
199268
run: |
@@ -213,6 +282,10 @@ jobs:
213282
kubectl get daemonset istio-cni-node -n kube-system || echo "CNI daemonset not found (expected for insecure mode)"
214283
kubectl logs -n kube-system daemonset/istio-cni-node --tail=20 || true
215284
285+
echo "=== Ztunnel Daemonset Status ==="
286+
kubectl get daemonset ztunnel -n istio-system || echo "Ztunnel daemonset not found (expected for non-ambient modes)"
287+
kubectl logs -n istio-system daemonset/ztunnel --tail=20 || true
288+
216289
echo "=== Webhook Configurations ==="
217290
kubectl get mutatingwebhookconfiguration istio-sidecar-injector -o yaml | grep -A5 -B5 caBundle || true
218291

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,6 @@ pre-commit run
757757
- **Q:** Why does Kubeflow use Istio CNI instead of standard Istio?
758758
**A:** Istio CNI provides better security by eliminating the need for privileged init containers, making it more compatible with Pod Security Standards (PSS). It also enables native sidecars support introduced in Kubernetes 1.28, which helps address issues with init containers and application lifecycle management.
759759
- **Q:** Why does Istio CNI fail on Google Kubernetes Engine (GKE) with "read-only file system" errors?
760-
**A:** GKE mounts `/opt/cni/bin` as read-only for security reasons, preventing the Istio CNI installer from writing the CNI binary. Use the GKE-specific overlay: `kubectl apply -k common/istio/istio-install/overlays/gke`. This overlay uses GKE's writable CNI directory at `/home/kubernetes/bin`. For more details, see [Istio CNI Prerequisites](https://istio.io/latest/docs/setup/additional-setup/cni/#prerequisites) and [Platform Prerequisites](https://istio.io/latest/docs/ambient/install/platform-prerequisites/).-`
760+
**A:** GKE mounts `/opt/cni/bin` as read-only for security reasons. Use the GKE-specific overlay: `kubectl apply -k common/istio/istio-install/overlays/gke` (or `overlays/ambient-gke` for ambient mode). These overlays use GKE's writable CNI directory at `/home/kubernetes/bin`. For details, see [Istio CNI Prerequisites](https://istio.io/latest/docs/setup/additional-setup/cni/#prerequisites).
761761

762762

common/istio/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@ GKE mounts `/opt/cni/bin` as read-only for security reasons, preventing the Isti
1919
kubectl apply -k istio-install/overlays/gke
2020
```
2121

22+
### Ambient Mode (Sidecar-free Service Mesh)
23+
Istio Ambient Mode eliminates sidecars, reducing resource overhead while maintaining full L4/L7 traffic processing capabilities.
24+
25+
```bash
26+
# OAuth2-Proxy
27+
kubectl apply -k istio-install/overlays/ambient-oauth2-proxy
28+
29+
# OAuth2-Proxy on Google Kubernetes Engine (GKE)
30+
kubectl apply -k istio-install/overlays/ambient-oauth2-proxy-gke
31+
```
32+
33+
**Important:** Ambient mode requires PSS Privileged (not Baseline or Restricted) for the `istio-system` namespace. The ztunnel component needs `CAP_SYS_ADMIN`, `CAP_NET_ADMIN`, and `CAP_NET_RAW` capabilities for transparent proxying and network namespace operations. The `istio-system` namespace is automatically configured with PSS privileged label when using ambient mode components.
34+
35+
**Note:** Ambient mode uses Kustomize components (`components/ambient-mode/`) for composable configuration without duplication.
36+
2237
### Insecure Istio (CNI-disabled)
2338
For environments that don't support CNI:
2439
```bash
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: apps/v1
2+
kind: DaemonSet
3+
metadata:
4+
name: istio-cni-node
5+
namespace: kube-system
6+
spec:
7+
template:
8+
spec:
9+
containers:
10+
- name: install-cni
11+
volumeMounts:
12+
- mountPath: /var/run/ztunnel
13+
name: cni-ztunnel-sock-dir
14+
- mountPath: /host/var/run/netns
15+
name: cni-netns-dir
16+
mountPropagation: HostToContainer
17+
volumes:
18+
- name: cni-ztunnel-sock-dir
19+
hostPath:
20+
path: /var/run/ztunnel
21+
type: DirectoryOrCreate
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: istio-cni-config
5+
namespace: kube-system
6+
data:
7+
AMBIENT_ENABLED: "true"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: ClusterRole
3+
metadata:
4+
name: istio-cni
5+
rules:
6+
- apiGroups:
7+
- ""
8+
resources:
9+
- pods
10+
- pods/status
11+
- nodes
12+
- namespaces
13+
verbs:
14+
- get
15+
- list
16+
- watch
17+
- patch
18+
- update
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: istio-system
5+
labels:
6+
pod-security.kubernetes.io/enforce: privileged
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: istiod
5+
namespace: istio-system
6+
spec:
7+
template:
8+
spec:
9+
containers:
10+
- name: discovery
11+
env:
12+
- name: PILOT_ENABLE_AMBIENT
13+
value: "true"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
apiVersion: kustomize.config.k8s.io/v1alpha1
2+
kind: Component
3+
4+
resources:
5+
- ztunnel.yaml
6+
- istio-namespace-pss-privileged.yaml
7+
8+
patches:
9+
- path: istiod-ambient-patch.yaml
10+
target:
11+
kind: Deployment
12+
name: istiod
13+
namespace: istio-system
14+
- path: cni-ambient-patch.yaml
15+
target:
16+
kind: DaemonSet
17+
name: istio-cni-node
18+
namespace: kube-system
19+
- path: cni-config-patch.yaml
20+
target:
21+
kind: ConfigMap
22+
name: istio-cni-config
23+
namespace: kube-system
24+
- path: cni-rbac-patch.yaml
25+
target:
26+
kind: ClusterRole
27+
name: istio-cni
28+
- target:
29+
kind: Namespace
30+
name: kubeflow
31+
patch: |-
32+
- op: add
33+
path: /metadata/labels/istio.io~1dataplane-mode
34+
value: ambient

0 commit comments

Comments
 (0)