More Info:
Worker nodes should be deployed in private subnets without public IPs so they are not directly reachable from the internet. Combine with a NAT/Service Gateway for outbound traffic.Risk Level
HighAddress
Compliance, SecurityCompliance Standards
- CIS OKE
Triage and Remediation
- Remediation
Remediation
Using Console
Using Console
Below are the remediation steps in the OCI Console to ensure OKE node pools use private nodes (no public IPs, only private subnets).
Result: Your OKE node pools now use private nodes (in private subnets, no public IPs) as required.
1. Prerequisites: Ensure You Have Private Subnets
- In the OCI Console, go to Networking → Virtual Cloud Networks.
- Select the VCN used by your OKE cluster.
- Under Subnets, verify you have:
- One or more private subnets (no Internet Gateway in their route table, typically using a NAT Gateway for outbound access).
- Proper security lists / NSGs to allow:
- Node-to-node traffic
- Node-to-control-plane traffic (per OKE docs)
- If you don’t have a private subnet:
- Click Create Subnet.
- Choose:
- Private Subnet: Yes
- Associate with the VCN used by the OKE cluster
- Attach route table that sends
0.0.0.0/0to a NAT Gateway (not Internet Gateway).
- Save the subnet.
2. Confirm Current Node Pool Configuration
- Go to Developer Services → Kubernetes Clusters (OKE).
- Select your Cluster.
- Click Node Pools.
- For each node pool:
- Check the Subnets column.
- Open the node pool, and in the Details panel verify:
- Whether it is using public subnets.
- Whether nodes have public IP addresses (this is typically controlled by the subnet type and advanced node settings).
3. Create a New Private Node Pool
- On the Node Pools tab of the cluster, click Create node pool.
- Fill in:
- Name: e.g.,
private-node-pool. - Kubernetes version: same as the cluster or as required.
- Node shape and Image: match or improve upon current node pool.
- Name: e.g.,
- Under Placement:
- Choose the same Availability Domains / Fault Domains as required.
- In Subnets, select only private subnets (created in step 1).
- Under Node configuration / Node metadata & networking (wording may vary slightly):
- Ensure Assign public IP addresses (or similar option) is unchecked/disabled.
- Confirm that Network security groups or Security lists allow needed traffic.
- Set the desired Node count.
- Click Create and wait for the node pool status to become Active and nodes to be Ready.
4. Migrate Workloads to the Private Node Pool
Usekubectl (or OKE Cloud Shell) for this part.- Label the new node pool’s nodes (optional but helpful):
- If your workloads use node selectors, affinities, or taints:
- Update Deployments/StatefulSets/DaemonSets to schedule to the new nodes (e.g.,
nodeSelector: { nodepool: private }).
- Update Deployments/StatefulSets/DaemonSets to schedule to the new nodes (e.g.,
- Gradually cordon and drain old (public) nodes:
- Verify all Pods are running on the new private nodes:
5. Delete the Old Public Node Pool
- In OCI Console, return to the Node Pools tab for your cluster.
- Confirm:
- No workloads are running on the old node pool’s nodes.
- Click on the old (public) node pool.
- Click Delete and confirm.
6. Validate Private-Only Access
- In Compute → Instances, locate instances from the new node pool:
- Confirm each instance has no public IP.
- Confirm they are placed in your private subnet.
- Confirm cluster behavior:
- Pods and services function normally.
- Outbound access (e.g., to Docker Hub, OCI Registry) works via the NAT Gateway, not Internet Gateway.
- If you use a bastion host or VPN / FastConnect, make sure admins can still reach nodes if required (SSH via private IP only).
Result: Your OKE node pools now use private nodes (in private subnets, no public IPs) as required.
Using CLI
Using CLI
To use private nodes in an OKE node pool via OCI CLI, you must:
Check:
Notes:
Before replacing, you should cordon & drain via
Then:
Compliance check:
After changes, confirm:
- Disable public IP assignment on the node pool, and
- Ensure the node pool uses private subnets (no internet gateway attached).
1. Prerequisites
- OCI CLI configured with appropriate privileges.
- OKE Cluster OCID.
- Private subnet OCIDs in the cluster VCN (subnets should not be associated to an Internet Gateway; use NAT Gateway for outbound if needed).
2. Identify the Node Pool
nodeConfigDetails.isPublicIpEnablednodeConfigDetails.placementConfigs[].subnetId
3. Update Node Pool to Disable Public IPs
isPublicIpEnabled must be false.Example:sizemust match or be set to your desired node count.- Ensure
subnetIdreferences a private subnet. - This setting applies to new/replaced nodes; existing ones keep their current IPs until cycled.
4. Move Nodes Fully to Private Subnets (If Needed)
If your current nodes are in public subnets or already have public IPs, you must replace them after updating the pool:kubectl to avoid workload disruption.5. (Alternative) Create a New Private Node Pool
If you prefer not to modify the existing pool:- Drain workloads from the old node pool.
- Delete the old (public) node pool:
Compliance check:
After changes, confirm:
isPublicIpEnabled should be false, and subnets should be private subnets only.Using Python
Using Python
To use private nodes in an OCI OKE node pool, you must ensure that:
Create a new private subnet if needed and use its
Key point: Using a private subnet (no Internet Gateway in its route table) ensures nodes get only private IPs. That is what makes the node pool “private” in OKE.
- The node pool’s worker nodes are placed in private subnets (no Internet Gateway route).
- Existing node pools that use public subnets are migrated to new node pools in private subnets.
1. Prerequisites
- Python 3.x
ociSDK installed:- OCI config file set up (
~/.oci/config) and a profile (e.g.,DEFAULT) with permissions for:ContainerEngineClient(OKE)VirtualNetworkClient(networking)
2. Network Setup (ensure private subnets)
- Identify / create a VCN.
- Create or identify a private subnet:
- Subnet is in the same VCN and AD as the cluster.
- Subnet uses a route table without an Internet Gateway (use a NAT gateway or Service Gateway for outbound if needed).
- Proper security lists / NSGs are applied.
subnet_id for the node pool.3. Create a New Private Node Pool with Python
You cannot “flip” a public node pool to private directly; you typically:- Create a new node pool using private subnets.
- Cordon & drain workloads from the old node pool.
- Delete the old node pool.
4. Migrate Workloads and Remove Old Public Node Pool
Once the new private node pool is active:- Update your cluster’s node selectors / taints so workloads can run on the new nodes.
- Cordon and drain nodes in the old (public) node pool from
kubectl: - Delete the old node pool via Python:
5. Optional: Enforce Private-Only Node Pools (Programmatically)
If you want to ensure that new node pools are always private, you can add a check in your automation that:- Validates
subnet_idis private (no IGW route) using the helper in step 2. - Rejects or fails creation if any subnet is public.
Using Terraform
Using Terraform
prohibit_public_ip_on_vnic on an existing subnet forces subnet replacement; plan this to avoid outages.After updating, terraform plan should show:prohibit_public_ip_on_vnic = truebeing set on the worker subnet (or a new private subnet created), and- the
oci_containerengine_node_poolusing that private subnet ID in itsplacement_configs.

