RUN apk add -U curl privoxy jq && \ mv /etc/privoxy/templates /etc/privoxy-templates && \ rm -rf /var/cache/apk/* /etc/privoxy/* && \ mv /etc/privoxy-templates /etc/privoxy/templates ADD --chown=privoxy:privoxy config \ /etc/privoxy/ ADD --chown=privoxy:privoxy k8s-only.action \ /etc/privoxy/ ADD --chown=privoxy:privoxy k8s-rewrite-internal.filter \ /etc/privoxy/ ADD k8s-api-proxy.sh /
EXPOSE 8118/tcp
ENTRYPOINT ["./k8s-api-proxy.sh"]
In the k8s-api-proxy
directory, create the config
file and add the following content to it:
#config directory confdir /etc/privoxy # Allow Kubernetes API access only actionsfile /etc/privoxy/k8s-only.action # Rewrite https://CLUSTER_IP to https://kubernetes.default filterfile /etc/privoxy/k8s-rewrite-internal.filter # Don't show the pod name in errors hostname k8s-privoxy # Bind to all interfaces, port :8118 listen-address :8118 # User cannot click-through a block enforce-blocks 1 # Allow more than one outbound connection tolerate-pipelining 1
In the same directory, create the k8s-only.action
file and add the following content to it. Note that CLUSTER_IP
will be replaced when k8s-api-proxy.sh
runs.
# Block everything... {+block{Not Kubernetes}} /
# ... except the internal k8s endpoint, which you rewrite (see # k8s-rewrite-internal.filter). {+client-header-filter{k8s-rewrite-internal} -block{Kubernetes}} CLUSTER_IP/
Create the k8s-rewrite-internal.filter
file and add the following content to it. Note that CLUSTER_IP
will be replaced when k8s-api-proxy.sh
runs.
CLIENT-HEADER-FILTER: k8s-rewrite-internal\ Rewrite https://CLUSTER_IP/ to https://kubernetes.default/ s@(CONNECT) CLUSTER_IP:443\ (HTTP/\d\.\d)@$1 kubernetes.default:443 $2@ig
Create the k8s-api-proxy.sh
file and add the following content to it.
#!/bin/sh set -o errexit set -o pipefail set -o nounset # Get the internal cluster IP export TOKEN=$(cat /run/secrets/kubernetes.io/serviceaccount/token) INTERNAL_IP=$(curl -H "Authorization: Bearer $TOKEN" -k -SsL https://kubernetes.default/api | jq -r '.serverAddressByClientCIDRs[0].serverAddress') # Replace CLUSTER_IP in the rewrite filter and action file sed -i "s/CLUSTER_IP/${INTERNAL_IP}/g"\ /etc/privoxy/k8s-rewrite-internal.filter sed -i "s/CLUSTER_IP/${INTERNAL_IP}/g"\ /etc/privoxy/k8s-only.action # Start Privoxy un-daemonized privoxy --no-daemon /etc/privoxy/config
Make k8s-api-proxy.sh
executable:
chmod +x k8s-api-proxy.sh
Build and push the container to your project.
docker build -t gcr.io/$PROJECT_ID/k8s-api-proxy:0.1 . docker push gcr.io/$PROJECT_ID/k8s-api-proxy:0.1
In Cloud Shell, log in to the client VM you created earlier:
gcloud compute ssh proxy-temp
Install the kubectl
tool:
sudo apt-get install kubectl
Save the project ID as an environment variable:
export PROJECT_ID=`gcloud config list --format="value(core.project)"`
Get the cluster credentials:
gcloud container clusters get-credentials frobnitz \ --zone us-central1-c --internal-ip
Create a Kubernetes deployment that exposes the container that you just created:
kubectl run k8s-api-proxy \ --image=gcr.io/$PROJECT_ID/k8s-api-proxy:0.1 \ --port=8118
Create the ilb.yaml
file for the internal load balancer and copy the following into it:
apiVersion:v1kind:Servicemetadata:labels:run:k8s-api-proxyname:k8s-api-proxynamespace:defaultannotations:cloud.google.com/load-balancer-type:"Internal"spec:ports:-port:8118protocol:TCPtargetPort:8118selector:run:k8s-api-proxytype:LoadBalancer
Deploy the internal load balancer:
kubectl create -f ilb.yaml
Check for the Service and wait for an IP address:
kubectl get service/k8s-api-proxy
The output will look like the following. When you see an external IP, the proxy is ready.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8s-api-proxy LoadBalancer 10.24.13.129 10.24.24.3 8118:30282/TCP 2m
The external IP address from this step is your proxy address.
Save the IP address of the ILB as an environment variable:
export LB_IP=`kubectl get service/k8s-api-proxy \ -o jsonpath='{.status.loadBalancer.ingress[].ip}'`
Save the cluster's controller IP address in an environment variable:
export CONTROLLER_IP=`gcloud container clusters describe frobnitz \ --zone=us-central1-c \ --format="get(privateClusterConfig.privateEndpoint)"`
Verify that the proxy is usable by accessing the Kubernetes API through it:
curl -k -x $LB_IP:8118 https://$CONTROLLER_IP/version
{ "major": "1", "minor": "15+", "gitVersion": "v1.15.11-gke.5", "gitCommit": "a5bf731ea129336a3cf32c3375317b3a626919d7", "gitTreeState": "clean", "buildDate": "2020-03-31T02:49:49Z", "goVersion": "go1.12.17b4", "compiler": "gc", "platform": "linux/amd64" }
Set the https_proxy
environment variable to the HTTP(S) proxy so that the kubectl
command can reach the internal load balancer from anywhere:
export https_proxy=$LB_IP:8118
Test your proxy and https_proxy
variable by running the kubectl
command:
kubectl get pods
You will get an output that looks like the following, which means that you successfully connected to the Kubernetes API through the proxy:
NAME READY STATUS RESTARTS AGE k8s-api-proxy-766c69dd45-mfqf4 1/1 Running 0 6m15s
Exit the client VM:
exit
To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, either delete the project that contains the resources, or keep the project and delete the individual resources.
If you don't want to delete the project, delete the GKE cluster:
gcloud container clusters delete frobnitz
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2019-07-02 UTC.