GKE Security

Security on GKE involves multiple layers: authentication and authorization, network security, encryption, secrets management, and compliance. GKE integrates deeply with Google Cloud security services like Cloud IAM, Secret Manager, and Binary Authorization to provide enterprise-grade security for Kubernetes workloads.

Security Architecture

GKE security operates at multiple levels:

graph TB subgraph authentication[Authentication] USER[User/Application] --> IAM[Cloud IAM] IAM --> GKE[GKE API Server] end subgraph authorization[Authorization] GKE --> RBAC[Kubernetes RBAC] RBAC --> POD[Pod Access] end subgraph network[Network Security] POD --> FW[Firewall Rules] POD --> NP[Network Policies] POD --> VPC[VPC Isolation] end subgraph encryption[Encryption] POD --> KMS[Cloud KMS] KMS --> PD[Encrypted Persistent Disk] KMS --> SECRETS[Encrypted Secrets] end style USER fill:#e1f5ff style GKE fill:#fff4e1 style POD fill:#e8f5e9 style KMS fill:#f3e5f5

Workload Identity

Workload Identity allows pods to assume Google Cloud service accounts, eliminating the need to store service account keys in pods or use instance service accounts.

How Workload Identity Works

graph LR POD[Pod] --> SA[Service Account] SA --> ANNOTATION[Annotation:<br/>iam.gke.io/gcp-service-account] ANNOTATION --> WI[Workload Identity Pool] WI --> CLOUD_IAM[Cloud IAM] CLOUD_IAM --> GCP_SA[Google Cloud<br/>Service Account] GCP_SA --> GCP_SERVICE[Google Cloud Service] style POD fill:#e1f5ff style GCP_SA fill:#fff4e1 style GCP_SERVICE fill:#e8f5e9

Components:

  1. Workload Identity Pool - Links GKE cluster to Cloud IAM
  2. Kubernetes Service Account - Kubernetes service account with annotation
  3. Google Cloud Service Account - GCP service account with necessary permissions
  4. IAM Policy Binding - Allows Kubernetes SA to assume GCP SA
  5. Pod - Uses Kubernetes service account to get temporary credentials

Setting Up Workload Identity

Step 1: Enable Workload Identity on Cluster

# Enable Workload Identity on cluster
gcloud container clusters update my-cluster \
  --zone us-central1-a \
  --workload-pool PROJECT_ID.svc.id.goog

Step 2: Enable Workload Identity on Node Pool

# Enable Workload Identity on node pool
gcloud container node-pools update default-pool \
  --cluster my-cluster \
  --zone us-central1-a \
  --workload-metadata=GKE_METADATA

Step 3: Create Google Cloud Service Account

# Create GCP service account
gcloud iam service-accounts create my-app-sa \
  --display-name="My App Service Account"

# Grant permissions
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="serviceAccount:my-app-sa@PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/storage.objectViewer"

Step 4: Create Kubernetes Service Account

# Create Kubernetes service account
kubectl create serviceaccount my-app-sa \
  --namespace default

# Annotate with GCP service account
kubectl annotate serviceaccount my-app-sa \
  --namespace default \
  iam.gke.io/gcp-service-account=my-app-sa@PROJECT_ID.iam.gserviceaccount.com

Step 5: Bind IAM Policy

# Allow Kubernetes SA to impersonate GCP SA
gcloud iam service-accounts add-iam-policy-binding \
  my-app-sa@PROJECT_ID.iam.gserviceaccount.com \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:PROJECT_ID.svc.id.goog[default/my-app-sa]"

Step 6: Use in Pod

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  serviceAccountName: my-app-sa
  containers:
  - name: app
    image: my-app:latest
    # Pod automatically gets GCP service account credentials
    # No need to configure GCP credentials

Pod Identity and Authentication

Google Cloud SDK Credential Chain

Pods using Workload Identity automatically get credentials through the Google Cloud SDK credential chain:

  1. Environment Variables - GOOGLE_APPLICATION_CREDENTIALS
  2. Metadata Server - From Workload Identity (default)
  3. Application Default Credentials - From gcloud CLI

The Google Cloud SDK in your application automatically uses Workload Identity credentials when available.

Testing Workload Identity

# Deploy test pod
kubectl run gcloud-test \
  --image=gcr.io/google.com/cloudsdktool/google-cloud-cli:latest \
  --serviceaccount=my-app-sa \
  --command -- sleep 3600

# Test access
kubectl exec -it gcloud-test -- gcloud storage ls

# Check credentials
kubectl exec -it gcloud-test -- env | grep GOOGLE

Network Security

Firewall Rules

Firewall rules provide network-level access control:

Default Firewall Rules:

  • Allow ingress from other nodes in cluster
  • Allow egress to internet
  • Allow ingress from load balancers

Custom Firewall Rules:

# Create firewall rule
gcloud compute firewall-rules create allow-internal \
  --network my-vpc \
  --allow tcp:8080 \
  --source-ranges 10.10.0.0/14 \
  --target-tags gke-my-cluster-node

Pod-Level Firewall:

  • Network policies for pod-to-pod isolation
  • Firewall rules for node-level isolation
  • Use both for defense in depth

Network Policies

Network policies provide pod-to-pod firewall rules:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432

Network Policy Use Cases:

  • Isolate namespaces
  • Restrict pod-to-pod communication
  • Allow only specific ingress/egress
  • Defense in depth with firewall rules

Private Clusters

Private clusters restrict network access for enhanced security:

# Create private cluster
gcloud container clusters create private-cluster \
  --zone us-central1-a \
  --enable-private-nodes \
  --enable-private-endpoint \
  --master-ipv4-cidr 172.16.0.0/28

Private Cluster Features:

  • Private nodes (no external IPs)
  • Private endpoint (API server only accessible from VPC)
  • Enhanced security
  • Requires VPN or bastion host for access

Secrets Management

Kubernetes Secrets

Basic secret management (encrypted at rest with etcd encryption):

apiVersion: v1
kind: Secret
metadata:
  name: app-secret
type: Opaque
stringData:
  username: admin
  password: secretpassword
---
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
    image: my-app:latest
    env:
    - name: USERNAME
      valueFrom:
        secretKeyRef:
          name: app-secret
          key: username
    - name: PASSWORD
      valueFrom:
        secretKeyRef:
          name: app-secret
          key: password

Google Secret Manager Integration

Use Secret Manager for secure secrets storage:

apiVersion: v1
kind: Secret
metadata:
  name: app-secret
  annotations:
    secret-manager.gke.io/secret-id: projects/PROJECT_ID/secrets/my-secret/versions/latest
type: Opaque

Secret Manager Benefits:

  • Centralized secret management
  • Automatic rotation
  • Audit logging
  • Version control
  • IAM-based access control

Using Secret Manager in Pods

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    spec:
      serviceAccountName: my-app-sa  # Needs Secret Manager access
      containers:
      - name: app
        image: my-app:latest
        env:
        - name: API_KEY
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: api-key

Encryption

Control Plane Encryption

GKE control plane encryption is enabled by default:

  • Encryption at Rest - etcd data encrypted with Google-managed keys
  • Encryption in Transit - TLS for API server communication
  • Customer-Managed Keys - Option to use Cloud KMS keys

Enable Customer-Managed Keys:

# Create KMS key
gcloud kms keyrings create my-keyring \
  --location us-central1

gcloud kms keys create my-key \
  --location us-central1 \
  --keyring my-keyring \
  --purpose encryption

# Create cluster with customer-managed key
gcloud container clusters create my-cluster \
  --zone us-central1-a \
  --database-encryption-key projects/PROJECT_ID/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key

Persistent Disk Encryption

Enable encryption in storage class:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: pd-ssd-encrypted
provisioner: pd.csi.storage.gke.io
parameters:
  type: pd-ssd
  encryptionKey: projects/PROJECT_ID/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key

Encryption Options:

  • Google-managed keys (default)
  • Customer-managed keys (Cloud KMS)
  • Automatic encryption for all volumes

Binary Authorization

Binary Authorization provides container image verification and policy enforcement.

Enabling Binary Authorization

# Enable Binary Authorization on cluster
gcloud container clusters update my-cluster \
  --zone us-central1-a \
  --enable-binary-authorization

Binary Authorization Policies

apiVersion: binaryauthorization.googleapis.com/v1
kind: Policy
metadata:
  name: projects/PROJECT_ID/policy
spec:
  admissionWhitelistPatterns:
  - namePattern: gcr.io/google_containers/*
  - namePattern: gcr.io/cloudsql-docker/*
  defaultAdmissionRule:
    evaluationMode: REQUIRE_ATTESTATION
    enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
    requireAttestationsBy:
    - projects/PROJECT_ID/attestors/my-attestor
  clusterAdmissionRules:
    us-central1-a.my-cluster:
      evaluationMode: REQUIRE_ATTESTATION
      enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
      requireAttestationsBy:
      - projects/PROJECT_ID/attestors/my-attestor

Binary Authorization Features:

  • Container image verification
  • Policy enforcement
  • Attestation-based admission
  • Integration with container registries

RBAC with Cloud IAM Integration

Mapping Cloud IAM to Kubernetes Users

GKE integrates Cloud IAM with Kubernetes RBAC:

# Grant IAM permissions
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="user:[email protected]" \
  --role="roles/container.developer"

# Grant cluster admin
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="user:[email protected]" \
  --role="roles/container.clusterAdmin"

IAM Roles:

  • container.viewer - View clusters
  • container.developer - Create and update resources
  • container.clusterAdmin - Full cluster administration
  • container.admin - Full project administration

Kubernetes RBAC

Combine IAM mapping with Kubernetes RBAC:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods", "services"]
  verbs: ["get", "list", "create", "update", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-binding
  namespace: default
subjects:
- kind: User
  name: [email protected]
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

Compliance and Audit Logging

Cloud Audit Logs

GKE API calls are logged to Cloud Audit Logs:

# View audit logs
gcloud logging read "resource.type=gke_cluster" \
  --limit 50 \
  --format json

Logged Events:

  • Cluster creation/deletion
  • Node pool operations
  • Configuration changes
  • API calls

VPC Flow Logs

Monitor network traffic:

# Enable VPC Flow Logs
gcloud compute networks subnets update my-subnet \
  --region us-central1 \
  --enable-flow-logs

Security Best Practices

  1. Enable Workload Identity - Use Workload Identity instead of service account keys

  2. Use Private Clusters - Restrict network access for production

  3. Enable Binary Authorization - Verify container images before deployment

  4. Implement Network Policies - Pod-to-pod network isolation

  5. Use Secret Manager - For sensitive data instead of Kubernetes secrets

  6. Enable Encryption - Use customer-managed keys for sensitive workloads

  7. Enable Shielded GKE Nodes - Enhanced node security

  8. Use Minimal Permissions - Follow least privilege principle

  9. Enable Audit Logging - Monitor all cluster operations

  10. Regular Updates - Keep cluster and nodes updated

  11. Multi-Factor Authentication - Require MFA for IAM users

  12. Separate Environments - Use different clusters for dev/staging/prod

Common Security Issues

Workload Identity Not Working

Problem: Pod can’t assume GCP service account

Solutions:

  • Verify Workload Identity is enabled on cluster and node pool
  • Check service account annotation
  • Verify IAM policy binding
  • Check IAM permissions
  • Review pod logs for credential errors

Access Denied Errors

Problem: kubectl access denied

Solutions:

  • Verify Cloud IAM permissions
  • Check RBAC permissions
  • Verify cluster endpoint access
  • Check IAM user permissions

Network Policy Not Enforcing

Problem: Network policies not working

Solutions:

  • Verify network policy is enabled on cluster
  • Check network policy syntax
  • Verify pod selectors
  • Review network policy logs

See Also