Google Cloud Code brings cloud-native development tasks into familiar local IDEs. It is most useful for applications packaged as containers and run on Kubernetes: you can build the application, inspect manifests, watch logs, debug supported workloads, and deploy through one workflow instead of moving between disconnected tools.
This guide takes a small web application from a local project folder to a Kubernetes deployment. Cloud Code labels can change between releases, so consult the current extension or plugin documentation if a menu name does not match what you see.
What Google Cloud Code Adds to Visual Studio Code and IntelliJ
Google Cloud Code does not replace Visual Studio Code, IntelliJ, Docker, Kubernetes, or your language tools. It is an IDE extension or plugin that brings those tools together into a more workable process for containerized applications.
For Kubernetes-focused development, Cloud Code can help you:
- Create or open starter projects and Kubernetes configurations.
- Validate Kubernetes manifests while you edit them.
- Build container images and run workloads against a selected Kubernetes context.
- Surface pod status, events, logs, and forwarded ports in the IDE.
- Start a supported debugger against an application running in a container.
- Deploy a tested configuration to an authorized Google Cloud Kubernetes target.
Visual Studio Code and IntelliJ support similar workflows through different interfaces. In Visual Studio Code, Cloud Code actions are commonly available from the Command Palette, Run and Debug view, and Cloud Code views. In IntelliJ, the plugin generally works through run configurations, tool windows, and IDE actions.
The example service is a small Python application named greeting. It listens on port 8080 and responds to requests such as /greet/Ada. The build and deployment configuration also creates a Kubernetes namespace named greeting.
Real story
I once opened Cloud Code to check a Kubernetes manifest and somehow spent ten minutes staring at a YAML file while the app was already building in the background. Then I clicked the wrong debug configuration, watched my local service restart twice, and proudly announced I had found the bug. The bug was me. The app was fine; my mouse was the problem.
Have a story of your own? Share it in the comments below.
1. Install Cloud Code and Prepare a Local Development Project
Begin with a functioning local development environment. Cloud Code can coordinate several tools, but it cannot make a stopped container runtime or a missing Kubernetes context suddenly cooperate.
1. Install the Extension or Plugin
Install the Cloud Code integration for your IDE:
- In Visual Studio Code, install the Cloud Code extension from the extension marketplace.
- In IntelliJ, install the Google Cloud Code plugin through the JetBrains plugin settings.
Next, verify that the supporting tools required for a practical web development stack are installed and available in your shell:
- A container runtime such as Docker.
kubectlfor communicating with Kubernetes.- A local Kubernetes environment, such as minikube, kind, or Docker Desktop Kubernetes.
- Skaffold, if Cloud Code does not install or manage it for your environment.
- The Google Cloud CLI when your team uses it for authentication or remote cluster credentials.
- Any language runtime and package manager required by the application.
Cloud Code and project templates may configure some dependencies for you. Even so, check the extension’s environment or diagnostics view after installation. Finding a missing command before a debugging session is much easier than finding it halfway through one.
2. Create a Source-Control-Friendly Project Layout
Put application code, container instructions, and Kubernetes resources in predictable locations. This project uses the following layout:
greeting/
├── app.py
├── requirements.txt
├── Dockerfile
├── skaffold.yaml
└── k8s/
├── namespace.yaml
├── deployment.yaml
└── service.yaml
Keep credentials, local overrides, and generated files out of source control. A repository should contain the configuration required to reproduce the application, not a developer’s access tokens or a file named definitely-not-a-secret.txt.
3. Add a Simple Application Entry Point
Here is a minimal Python service:
import os
from flask import Flask, jsonify
app = Flask(__name__)
@app.get("/greet/
The app listens on all interfaces because it will run inside a container. Binding only to 127.0.0.1 inside the container can leave the process looking healthy while preventing the Kubernetes Service from reaching it.
4. Define the Container Image
A simple Dockerfile for the service could be:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["python", "app.py"]
Use the following dependencies:
Flask>=3.0,<4.0
debugpy
Including debugpy makes the Python debug adapter available when Cloud Code starts a supported Kubernetes debugging session in Visual Studio Code.
If you are starting with an existing project, build the image locally once before involving Kubernetes. That keeps early failures focused on application dependencies, file paths, and Dockerfile instructions.
IDE-Specific Notes
Visual Studio Code: Use the Command Palette to search for Cloud Code commands, including Kubernetes run and debug actions. The extension’s status information can help identify missing local prerequisites.
IntelliJ: After installing the plugin, look for Cloud Code run configurations and Kubernetes-related tool windows. If a run configuration is not created automatically, start with the plugin’s project or Kubernetes actions instead of a generic application run configuration.
2. Configure the Application for Cloud Code’s Kubernetes Workflow
Cloud Code works best when the application, container image, and Kubernetes resources agree on the basics: image name, labels, ports, environment variables, namespace, and target context. A mismatch in any of these can leave you with a deployment that appears active but does not do anything useful.
1. Create the Kubernetes Namespace
The example sends all namespaced resources to greeting. Include the Namespace manifest so Skaffold can create it as part of the workflow:
apiVersion: v1
kind: Namespace
metadata:
name: greeting
Save this as k8s/namespace.yaml.
2. Create a Kubernetes Deployment
The Deployment describes the application container and the state Kubernetes should maintain.
apiVersion: apps/v1
kind: Deployment
metadata:
name: greeting
namespace: greeting
labels:
app: greeting
spec:
replicas: 1
selector:
matchLabels:
app: greeting
template:
metadata:
labels:
app: greeting
spec:
containers:
- name: greeting
image: greeting-service
ports:
- containerPort: 8080
env:
- name: GREETING_PREFIX
value: "Hello"
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "250m"
memory: "256Mi"
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 3
periodSeconds: 5
One replica is generally enough for local development. Resource settings should still be realistic enough to expose obvious startup or memory problems before they appear in a later environment.
The greeting-service image name deliberately matches the Skaffold artifact defined below. Skaffold replaces this manifest reference with the tagged image it builds, including the configured remote repository when the remote profile is active.
3. Create a Kubernetes Service
The Service gives the Deployment’s pods a stable endpoint.
apiVersion: v1
kind: Service
metadata:
name: greeting
namespace: greeting
spec:
selector:
app: greeting
ports:
- name: http
port: 80
targetPort: 8080
type: ClusterIP
A request follows this path:
Local browser or test client
↓
Forwarded local port
↓
Kubernetes Service on port 80
↓
Container port 8080
↓
Python application
The Service selector, Deployment labels, and container port must agree. If the Service selects app: greetings while the Deployment labels its pods app: greeting, Kubernetes creates both resources, but the Service has no usable endpoints.
4. Add a Skaffold Configuration
Create skaffold.yaml with a local default workflow and a separate remote profile:
apiVersion: skaffold/v4beta11
kind: Config
metadata:
name: greeting
build:
tagPolicy:
gitCommit: {}
artifacts:
- image: greeting-service
context: .
docker:
dockerfile: Dockerfile
local:
push: false
manifests:
rawYaml:
- k8s/namespace.yaml
- k8s/deployment.yaml
- k8s/service.yaml
deploy:
kubectl: {}
profiles:
- name: remote
build:
local:
push: true
The default configuration supports local development:
- It builds the
greeting-service artifact from the supplied Dockerfile.
- It does not push the image to a registry.
- It deploys the namespace, Deployment, and Service manifests.
- It relies on a local cluster that can access images built by the selected local container runtime.
If your local cluster does not share Docker’s image store, configure its supported image-loading method before starting the workflow.
The remote profile supports a remote development workflow, keeping the same manifests and artifact but pushing the generated image. Provide the approved remote repository as Skaffold’s default repository when deploying remotely:
export REMOTE_IMAGE_REPOSITORY='REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY'
skaffold run -p remote --default-repo="$REMOTE_IMAGE_REPOSITORY"
With that command, Skaffold builds and pushes an image under the approved repository, such as:
REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/greeting-service:TAG
It also substitutes that final image reference for greeting-service in the Deployment before applying it. Configure Cloud Code’s remote run or deploy action to select the remote profile and use the same default repository. The command above is the equivalent direct Skaffold invocation.
For local development, Cloud Code uses the default profile. Its equivalent command is:
skaffold dev
Cloud Code’s Kubernetes debug action uses the same build and deployment inputs while starting a debug-capable workload.
5. Select a Local Kubernetes Target
Before starting the application, confirm that the active Kubernetes context points to your local cluster:
kubectl config current-context
kubectl get nodes
kubectl get namespace greeting
Cloud Code uses the Kubernetes context selected by your project or command configuration. Give local, staging, and production contexts clear names. A vague context name is easy to overlook until it sends a change to the wrong place.
Also confirm how your local cluster receives container images:
- Some local Kubernetes setups can use images built directly by the local container runtime.
- Others require images to be loaded into the cluster.
- Remote clusters need images pushed to an accessible registry.
6. Use Validation Before Running
Cloud Code can provide YAML diagnostics and Kubernetes-aware validation as you edit manifests. Use those checks to catch malformed YAML, unsupported fields, missing references, and structural errors early.
Validation cannot establish every runtime detail. For example:
- A malformed
targetPort may be highlighted quickly.
- A valid but incorrect image name may not fail until Kubernetes tries to pull it.
- A readiness probe path can be syntactically valid but still return
404 when the container starts.
Treat IDE validation as the first check, not the final one.
3. Run, Debug, and Inspect the Application Without Leaving the IDE
Running through Cloud Code involves more than starting a container. The workflow ties together the build, Kubernetes workload, logs, port forwarding, and debugging tools, making it easier to see where a failure starts.
1. Start the Application on the Local Cluster
Use Cloud Code’s Kubernetes run action for the current project. This normally starts the default Skaffold development workflow:
- Build or rebuild the application image.
- Make the image available to the selected cluster.
- Apply the Namespace, Deployment, and Service manifests.
- for the workload to start.
- Stream application output and Kubernetes status into the IDE.
Watch the application log alongside the Kubernetes resource state. A Python stack trace points toward application code. A pod stuck in image-pull status points toward image availability or permissions. They are different problems, even though both can leave a browser without a response.
2. Test the Service Through a Forwarded Port
Cloud Code may create a port forward automatically, depending on the project configuration. You can also run the equivalent local command:
kubectl -n greeting port-forward service/greeting 8080:80
Then test the application:
curl http://localhost:8080/greet/Ada
Expected output:
{"message":"Hello, Ada!"}
The request reaches the Service on port 80, which forwards traffic to port 8080 in the container. Testing through the Service checks more than the application process by itself.
3. Start a Supported Debugging Session
Python breakpoint debugging in this guide is limited to Cloud Code for Visual Studio Code. Cloud Code for Visual Studio Code supports Python Kubernetes debugging, including breakpoints in the running containerized application.
Cloud Code for IntelliJ does not provide the equivalent Cloud Code Python breakpoint workflow. IntelliJ users can still build, deploy, inspect Kubernetes resources, and view logs for this Python service, but should use Visual Studio Code for the Python breakpoint steps below. Cloud Code debugging in IntelliJ should be limited to the languages and debugger workflows supported by that IDE and plugin version.
In Visual Studio Code, choose Cloud Code’s Kubernetes debug action instead of the standard local run action. For supported runtimes, Cloud Code prepares the workload and connects the IDE debugger.
Set a breakpoint in the request handler:
@app.get("/greet/
Send the request again:
curl http://localhost:8080/greet/Ada
When the breakpoint is hit, inspect:
- The value of
name.
- The
GREETING_PREFIX environment variable.
- The call stack.
- Any values returned by downstream application code.
The debugger connection uses a different port from the application’s HTTP port. Let Cloud Code handle debugger port forwarding and attachment. Manually forwarding the wrong port can leave you staring at a perfectly healthy pod.
4. Make a Focused Change and Repeat
Change the Deployment environment variable:
env:
- name: GREETING_PREFIX
value: "Welcome"
Run or debug again, then repeat the request:
curl http://localhost:8080/greet/Ada
The expected response is now:
{"message":"Welcome, Ada!"}
Whether source edits synchronize automatically depends on the project’s Skaffold and Cloud Code configuration. Some changes can be synchronized or rebuilt incrementally; others require a complete image rebuild and redeployment. Check the behavior for your language and generated project instead of assuming every file save updates the container.
Troubleshooting Common Local Failures
CrashLoopBackOff
The container starts and then exits repeatedly. Read the pod logs and inspect the previous container attempt:
kubectl -n greeting logs deployment/greeting
kubectl -n greeting logs deployment/greeting --previous
Common causes include a missing package, an incorrect startup command, an unavailable required environment variable, or a readiness probe that does not match the application.
The local cluster is unavailable
If kubectl get nodes fails, restore the Kubernetes connection before changing application code. Confirm that the local cluster and container runtime are running and that the intended context is active.
The image build fails
Read the first meaningful build error rather than only the final failure line. Frequent causes include an incorrect Dockerfile path, a dependency that cannot be installed, or a .dockerignore rule that excludes source files by mistake.
Port forwarding does not work
Check that the Service selects the running pods and maps to the correct target port:
kubectl -n greeting get pods -l app=greeting
kubectl -n greeting get service greeting
kubectl -n greeting get endpointslice -l kubernetes.io/service-name=greeting
EndpointSlices show which endpoints the Service selected. If no EndpointSlices contain ready addresses, compare the Service selector with the pod labels. If ready endpoints exist but requests still fail, inspect the container port and application binding address.
ImagePullBackOff appears on a remote target
The manifest may reference an image that was not pushed, was tagged differently, or cannot be pulled by the cluster. Confirm the final image reference printed by Skaffold and the target environment’s registry access policy.
4. Deploy the Validated Application to a Google Cloud Kubernetes Target
After the local workflow is stable, move to an authorized Google Cloud Kubernetes target, such as the cluster selected by your team. Use the remote Skaffold profile instead of the local default.
1. Confirm the Deployment Target
Before deploying, confirm all of the following:
- The active Kubernetes context points to the intended cluster.
- The
greeting namespace is the intended namespace.
- Your credentials are valid for that cluster and namespace.
REMOTE_IMAGE_REPOSITORY identifies the approved registry location.
- The deployment configuration uses release-safe values rather than local-only settings.
Useful checks include:
kubectl config current-context
kubectl get namespace greeting
kubectl get nodes
The included Namespace manifest creates greeting if it does not already exist. Because both the Deployment and Service explicitly specify that namespace, rollout, log, and verification commands must use -n greeting.
2. Build and Publish a Tagged Image
A deployed workload needs an image reference that the remote cluster can pull. The remote Skaffold profile pushes the image, while the gitCommit tag policy generates a tag from the repository state.
Set the approved repository and run the remote profile:
export REMOTE_IMAGE_REPOSITORY='REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY'
skaffold run -p remote --default-repo="$REMOTE_IMAGE_REPOSITORY"
Use your team’s established build and registry workflow through Cloud Code or the underlying Skaffold configuration. The key requirement is that the final Deployment reference the image that was actually built and published.
Do not put registry passwords, API keys, or application secrets directly in a Kubernetes manifest. Use the team-approved secret mechanism instead, and keep secret values out of terminal history, source control, and screenshots.
3. Deploy Through Cloud Code and Inspect the Rollout
In Cloud Code, select the remote deployment configuration that uses the remote Skaffold profile and the approved default repository. Watch the deployment output, then confirm that the workload becomes ready:
kubectl -n greeting rollout status deployment/greeting
kubectl -n greeting get pods,service
A successful apply command only means Kubernetes accepted the resource definitions. It does not show that the application is healthy, reachable, or serving the correct revision.
Inspect the logs after the rollout:
kubectl -n greeting logs deployment/greeting --tail=100
Check for normal startup output, unexpected exceptions, connection failures, and repeated restarts.
4. Verify a Representative Request
Check more than pod readiness. Send a request through the route that users or dependent services will actually use.
For a service intended to remain internal, test from an approved in-cluster client or your team’s standard verification path. For an externally exposed service, use the configured endpoint and verify:
- The expected response body.
- The expected HTTP status code.
- The deployed version or build identifier, if the application exposes one.
- Relevant health and readiness behavior.
A Deployment can have ready pods while its Service selector is wrong, its route is missing, or its application returns an error for real requests. Verification closes the gap between “Kubernetes created it” and “the application works.”
5. Turn the First Cloud Code Workflow Into a Repeatable Development Loop
Cloud Code’s value is not limited to the first successful deployment. The important part is the repeatable loop: edit, validate, run, debug, deploy, verify, and clean up.
Keep Dockerfiles, Kubernetes manifests, Skaffold configuration, and run instructions under version control. When developers rely on different hidden local settings to run the same application, debugging becomes an exercise in archaeology rather than a code investigation.
Keep Environments Separate
Use separate Cloud Code targets, Kubernetes contexts, namespaces, and configuration overlays for development, staging, and production. Make the target clear in run and deploy configuration names.
Local development can use faster rebuild settings and a local image workflow. A remote environment should use tagged images, controlled access, approved registry paths, and deployment checks appropriate to the team’s release process.
Use Cloud Code for the Development Loop, Not Every Delivery Responsibility
Cloud Code is well suited to developers working with containerized applications and Kubernetes resources from Visual Studio Code or IntelliJ. It is particularly useful when a problem may be in the code, container image, manifest, Service wiring, or runtime configuration.
A team’s automated delivery pipeline should still manage repeatable shared releases, policy checks, approvals, and production promotion. Cloud Code helps produce a validated change; it does not replace disciplined release practices.
Deployment-Readiness Checklist
Before deploying beyond a local cluster, check the following:
- The selected Kubernetes context and
greeting namespace are correct.
- The remote profile and approved image repository are selected.
- The image tag matches the intended build.
- The image has been published where the target cluster can pull it.
- No secrets are hard-coded in source files, Dockerfiles, or manifests.
- Deployment labels and Service selectors match.
- Container ports, Service ports, and application binding ports align.
- Readiness and health checks reflect real application behavior.
- Resource requests and limits are present and reasonable.
- The rollout status, pod logs, and representative request have been checked.
- The rollback approach and cleanup steps are understood before release.
A dependable Cloud Code workflow is straightforward: make a small change, validate the configuration, run it on the correct Kubernetes target, debug with real logs and supported breakpoints, then deploy a tagged image and verify the result. Keeping each step explicit makes failures easier to diagnose and successful deployments easier to repeat.



