> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Install Istio via CLI

> Guide to installing Istio with istioctl, deploying Bookinfo, and demonstrating automatic namespace and manual per-workload sidecar injection in Kubernetes

In this lesson you'll install Istio into an existing Kubernetes cluster, deploy the Bookinfo sample application, and demonstrate both automatic namespace injection and manual (per-workload) injection of the Istio sidecar proxy.

This guide follows a step-by-step flow:

1. Deploy the Bookinfo sample (pre-Istio).
2. Install `istioctl`.
3. Install the Istio control plane (demo profile).
4. Enable automatic sidecar injection for a namespace.
5. Manually inject the sidecar into an individual workload in an unlabeled namespace.

Prerequisites

| Requirement                                                           | Why it matters                                                                       |
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| A running Kubernetes cluster with `kubectl` configured                | You need cluster access to deploy resources and inspect pods                         |
| Cluster privileges to install cluster components and label namespaces | Installing Istio and modifying namespace labels requires sufficient RBAC permissions |
| Optional: Familiarity with Kubernetes `kubectl` basics                | Helpful for troubleshooting and pod inspection                                       |

***

## 1) Deploy the Bookinfo sample (pre-Istio)

First apply the Bookinfo sample so we have workloads to inject later. This deploys several microservices into the `default` namespace.

```bash theme={null}
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.11/samples/bookinfo/platform/kube/bookinfo.yaml
```

Verify pods are being created in `default`:

```bash theme={null}
kubectl get pods
```

Sample output (initial state, containers are being created):

```text theme={null}
NAME                           READY   STATUS              RESTARTS   AGE
details-v1-65599dcf88-k44bb    0/1     ContainerCreating   0          6s
productpage-v1-9487c9c5b-9cqhs 0/1     ContainerCreating   0          5s
ratings-v1-59b99c644-fhsp8     0/1     ContainerCreating   0          6s
reviews-v1-5985998544-k4lph    0/1     ContainerCreating   0          6s
reviews-v2-86d6cc668-qntwq     0/1     ContainerCreating   0          6s
reviews-v3-dbb5fb5dd-ffg9v     0/1     ContainerCreating   0          6s
```

Inspect a pod to confirm it currently has only the application container (no Istio proxy yet):

```bash theme={null}
kubectl describe pod details-v1-65599dcf88-k44bb
```

Relevant excerpt (shows a single container `details`):

```text theme={null}
Containers:
  details:
    Image:          docker.io/istio/examples-bookinfo-details-v1:1.16.2
    Port:           9080/TCP
    State:          Running
    Ready:          True
```

At this point Bookinfo is running, but Istio is not yet installed in the cluster.

***

## 2) Install istioctl (download the client)

Check whether `istioctl` is already present:

```bash theme={null}
istioctl version
```

If not installed, download the Istio release used in this demo (1.26.3):

```bash theme={null}
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.26.3 sh -
```

Add the `istioctl` binary directory to your `PATH` (adjust the path as needed for your user/home location):

```bash theme={null}
export PATH="$PATH:/root/istio-1.26.3/bin"
```

Confirm `istioctl` is available. At this point it will typically show a client version and note that Istio is not installed in-cluster:

```bash theme={null}
istioctl version
```

Sample output:

```text theme={null}
client version: 1.26.3
Istio not installed
```

***

## 3) Install Istio control plane (demo profile)

Install the Istio control plane into your cluster using the `demo` profile, which is suitable for learning and demos:

```bash theme={null}
istioctl install --set profile=demo -y
```

You should see output indicating core components and control plane services have been installed:

```text theme={null}
✔ Istio core installed ⛵
✔ Istiod installed 🧠
✔ Egress gateways installed ✈️
✔ Ingress gateways installed ✈️
✔ Installation complete
```

Verify the Istio system components are running in the `istio-system` namespace:

```bash theme={null}
kubectl get pods -n istio-system
```

Expect pods such as `istiod-...`, `istio-ingressgateway-...`, and `istio-egressgateway-...`.

***

## 4) Enable automatic sidecar injection for a namespace

Use `istioctl analyze` to surface common configuration hints. For example, analyze the `default` namespace:

```bash theme={null}
istioctl analyze -n default
```

If the namespace is not enabled for automatic injection, you may see an info message such as:

```text theme={null}
Info [IST0102] (Namespace default) The namespace is not enabled for Istio injection. Run 'kubectl label namespace default istio-injection=enabled' to enable it, or 'kubectl label namespace default istio-injection=disabled' to explicitly mark it as not needing injection.
```

Enable automatic sidecar injection for the namespace (for this demo we use `default`):

```bash theme={null}
kubectl label namespace default istio-injection=enabled --overwrite
```

Important: labeling a namespace does not restart existing pods. To apply injection to running workloads you must restart them (or delete/recreate them). Restart one or more deployments so the sidecar is injected:

```bash theme={null}
kubectl rollout restart deployment details-v1 productpage-v1
```

Check pods; injected workloads should now show `2/2` (application container + `istio-proxy`):

```bash theme={null}
kubectl get pods
```

Example showing injected pods:

```text theme={null}
details-v1-...    2/2   Running   0   14s
productpage-v1-...2/2   Running   0   13s
ratings-v1-...    1/1   Running   0   14s   # not yet restarted in this snapshot
```

Describe an injected pod to confirm the injected `istio-proxy` container:

```bash theme={null}
kubectl describe pod details-v1-...
```

Excerpt showing the proxy container:

```text theme={null}
Containers:
  details:
    Image: docker.io/istio/examples-bookinfo-details-v1:1.16.2
    Port: 9080/TCP
  istio-proxy:
    Image: docker.io/istio/proxyv2:1.26.3
    Port: 15090/TCP
    Args:
      proxy sidecar --domain $(POD_NAMESPACE).svc.cluster.local ...
    Readiness: http-get http://:15021/healthz/ready ...
```

This confirms the Istio sidecar proxy (version 1.26.3) was injected and is running alongside the application container.

***

## 5) Manual (per-workload) injection into an unlabeled namespace

Automatic namespace injection is convenient, but there are cases where you want to inject only specific workloads within a namespace. Manual injection—by annotating the pod or deployment manifest—lets you do that without labeling the namespace.

Create a new namespace named `db` (do not label it for injection):

```bash theme={null}
kubectl create ns db
kubectl get ns --show-labels
```

Run a simple Redis pod without injection:

```bash theme={null}
kubectl run redis-no-proxy --image=redis -n db
kubectl get pods -n db
```

You will see `redis-no-proxy` running with only one container (no `istio-proxy`).

Analyze the namespace to confirm it's not enabled for injection:

```bash theme={null}
istioctl analyze -n db
```

You should receive the same IST0102 hint indicating the namespace is not enabled for injection.

To inject the sidecar for a single workload without labeling the namespace, add the injector annotation `sidecar.istio.io/inject: "true"` to that pod or deployment. A simple way is to create the pod manifest locally and apply it.

Create a pod manifest using a dry-run:

```bash theme={null}
kubectl run redis-istio-proxy --image=redis -n db --dry-run=client -o yaml > pod.yaml
```

Edit `pod.yaml` and add the injector annotation under `metadata`, for example:

```yaml theme={null}
metadata:
  name: redis-istio-proxy
  namespace: db
  annotations:
    sidecar.istio.io/inject: "true"
```

Apply the manifest:

```bash theme={null}
kubectl apply -f pod.yaml
```

After applying, check pods in `db`:

```bash theme={null}
kubectl get pods -n db
```

You should see two pods:

* `redis-no-proxy` with `1/1` (application container only)
* `redis-istio-proxy` with `2/2` (application container + `istio-proxy`)

Describe the injected pod to inspect the proxy container and Istio environment variables:

```bash theme={null}
kubectl describe pod redis-istio-proxy -n db
```

Excerpt showing both containers and Istio metadata:

```text theme={null}
Containers:
  redis-istio-proxy:
    Image: redis
    State: Running
  istio-proxy:
    Image: docker.io/istio/proxyv2:1.26.3
    Args: proxy sidecar --domain $(POD_NAMESPACE).svc.cluster.local ...
Environment:
  PILOT_CERT_PROVIDER: istiod
  CA_ADDR: istiod.istio-system.svc:15012
  POD_NAME: redis-istio-proxy
  POD_NAMESPACE: db
ISTIO_META_INTERCEPTION_MODE: REDIRECT
ISTIO_META_WORKLOAD_NAME: redis-istio-proxy
```

This demonstrates per-workload injection via annotation, without labeling the entire namespace.

<Callout icon="lightbulb" color="#1CB2FE">
  Automatic namespace injection (labeling the namespace) is the simpler and recommended approach for most environments. Use the annotation `sidecar.istio.io/inject: "true"` when you need to inject only specific workloads in an otherwise unlabeled namespace. Note: some legacy helpers such as `istioctl kube-inject` have been deprecated or removed in recent Istio releases, so prefer annotation-based injection or `istioctl`-based installation workflows.
</Callout>

***

## Quick reference: common commands

| Task                             | Command                                                                                                                    |                              |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| Apply Bookinfo sample            | `kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.11/samples/bookinfo/platform/kube/bookinfo.yaml` |                              |
| Check pods                       | `kubectl get pods`                                                                                                         |                              |
| Describe pod                     | `kubectl describe pod <pod-name>`                                                                                          |                              |
| Download Istio                   | \`curl -L [https://istio.io/downloadIstio](https://istio.io/downloadIstio)                                                 | ISTIO\_VERSION=1.26.3 sh -\` |
| Add istioctl to PATH             | `export PATH="$PATH:/root/istio-1.26.3/bin"`                                                                               |                              |
| Install Istio (demo)             | `istioctl install --set profile=demo -y`                                                                                   |                              |
| Analyze namespace                | `istioctl analyze -n <namespace>`                                                                                          |                              |
| Label namespace for injection    | `kubectl label namespace default istio-injection=enabled --overwrite`                                                      |                              |
| Restart deployments to inject    | `kubectl rollout restart deployment <deployment-name>`                                                                     |                              |
| Create namespace                 | `kubectl create ns db`                                                                                                     |                              |
| Create pod manifest with dry-run | `kubectl run redis-istio-proxy --image=redis -n db --dry-run=client -o yaml > pod.yaml`                                    |                              |
| Apply manifest                   | `kubectl apply -f pod.yaml`                                                                                                |                              |

***

## Summary

* Installed `istioctl` (client v1.26.3) and the Istio control plane using the `demo` profile.
* Deployed the Bookinfo sample before installing Istio to illustrate pre- and post-injection behavior.
* Enabled automatic sidecar injection by labeling a namespace, then restarted specific workloads to have the `istio-proxy` injected.
* Demonstrated manual, per-workload injection by annotating a pod manifest so the admission webhook would add the sidecar in an otherwise unlabeled namespace.

Keep both automatic and manual injection workflows in mind — they are commonly tested and useful in real-world cluster operations and troubleshooting.

Links and references

* [Istio Documentation — Install Istio](https://istio.io/latest/docs/setup/install/)
* [Istio Download Page / istioctl](https://istio.io/latest/docs/setup/getting-started/#download)
* [Bookinfo sample (Istio repo)](https://github.com/istio/istio/tree/release-1.11/samples/bookinfo)
* [Kubernetes Basics](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/istio-certified-associate/module/65ee174b-536e-4657-9b6f-85c90c7612da/lesson/f9286a62-5585-445c-b649-8323b83fae22" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/istio-certified-associate/module/65ee174b-536e-4657-9b6f-85c90c7612da/lesson/eb471648-119e-4abc-b769-4b7f99bfadd1" />
</CardGroup>
