If you're starting using Google Cloud Platform, maybe after following my guide on deploying your first service to GKE, you'll probably want to setup a few command-line tools to be able to access your Kubernetes cluster from your terminal.
The usual tool to do that is kubectl
, but as we're in the context of GCP/GKE here, we'll use the gcloud
utility to set everything up.
Install gcloud
and init
Google provides an interactive installer which makes this step easy.
Answers to the installation questions are obvious enough that we don't have to detail them here.
Once gcloud
installed, start a new terminal session to load the new $PATH
and the command completion.
Init gcloud
Run gcloud init
in your new terminal to initialize the tool.
It will send you to a Google login page so that you can choose the Google account you want to connect with when using gcloud
. Once you've selected and authorized the correct account, go back to your terminal.
It will ask you to pick the GCP project you'd like to use: choose the one that holds the GCP resources you want to work with.
If you have several projects you'd like to be able to access, you can run gcloud init
again and choose to create a new configuration for those projects (connecting to a different Google account if necessary).
You will then be able to switch between configurations using gcloud configurations activate <config name>
.
Your project might have a randomly generated name, something like proud-dolphin-461842
. If you don't know which to choose, head over to your Cloud Console home: your project ID is there:
You're then asked whether you'd like to configure a default Compute Region and Zone. You should say yes. I'm not sure which use case makes it less practical to do it, but if you don't you'll have to add a --region
or --zone
argument to all your gcloud
calls.
Choose the region/zone where your resources are hosted. If you came from my GKE deployment guide, that would be the region you chose to create your cluster in.
Install the interactive CLI
gcloud
comes with a very handy interactive CLI to help you discover commands and their parameters. It's a beta feature that you can access using gcloud beta interactive
.
The first run of this command will install the component for you. Then, it'll run it:
Personally, I have added an alias to my zsh profile so that ig
will open this interactive CLI:
Install kubectl
component
Run the following to install kubectl
on your machine:
gcloud components install kubectl
You might a warning at the end of the installation, letting you know another version of kubectl
has been found on your computer. It can happen if you've installed Docker for Mac for instance.
To make sure you're using gcloud's version of kubectl
, use which kubectl
; the tool's path should look like this: /Users/olance/google-cloud-sdk/bin/kubectl
.
If it doesn't, tweak your $PATH
variable or remove the other version you've got.
Configure kubectl
for your GKE cluster
Once again, gcloud
will help you configure things properly.
Just run this command to have a kubectl
config generated for your GKE cluster:
If you're not sure what the name of your cluster is, gcloud
can tell you:
$ gcloud container clusters list
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
test-cluster europe-west1-b 1.12.8-gke.10 35.195.214.142 n1-standard-1 1.12.8-gke.10 1 RUNNING
Finally, if you've got a single cluster, or at least one main cluster you want to be working with, I highly encourage you to set it default in your config:
$ gcloud config set container/cluster test-cluster
Updated property [container/cluster].
This will automatically fill in the --cluster
argument in commands that require it.
Explore your Kubernetes resources
Now that everything is set up, you can start playing!
gcloud
vs. kubectl
Since you are on GKE, you have to keep in mind that it brings its own concepts on top of those from Kubernetes. This will help you know which tool to use when you want to get detailed information about a resource.
I covered the subject in my introduction to deploying to GKE.
As a result, you'll use kubectl
to get information on your nodes, pods, deployments, services, config maps and secrets (kubectl api-resources
will give you a full list), whereas gcloud
can be used to get information on your cluster, node pools, and the VM instances that are used to concretize your k8s nodes.
kubectl
: get & describe
Your best friends to learn more about your k8s resources are kubectl get <type>
and kubectl describe <type>/<name>
.
To get started, you can try kubectl get all
:
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/wordpress-d74bfbbc4-qg6fl 1/1 Running 0 3d
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.119.0.1 <none> 443/TCP 3d
service/wordpress-dq858 LoadBalancer 10.119.13.142 34.76.216.33 80:32647/TCP 3d
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deployment.apps/wordpress 1 1 1 1 3d
NAME DESIRED CURRENT READY AGE
replicaset.apps/wordpress-d74bfbbc4 1 1 1 3d
replicaset.apps/wordpress-ff54c57ff 0 0 0 3d
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/wordpress-hpa Deployment/wordpress 1%/80% 1 1 1 3d
Here I can see I've got one pod running, two services, one deployment, two replicasets (including an obsolete one) and one horizontal pod autoscaler, which is used to automatically spin up new pods for the wordpress deployment.
Let's delete the useless replicaset:
$ kubectl delete replicaset.apps/wordpress-ff54c57ff
replicaset.apps "wordpress-ff54c57ff" deleted
I want to learn more about the pod:
$ kubectl describe pod/wordpress-d74bfbbc4-qg6fl
Name: wordpress-d74bfbbc4-qg6fl
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: gke-test-cluster-default-pool-7fa0b2b7-pdqm/10.132.0.2
Start Time: Sun, 26 Sep 2019 11:20:21 +0200
Labels: app=wordpress
pod-template-hash=d74bfbbc4
Annotations: kubernetes.io/limit-ranger: LimitRanger plugin set: cpu request for container wordpress
Status: Running
IP: 10.52.0.10
Controlled By: ReplicaSet/wordpress-d74bfbbc4
Containers:
wordpress:
Container ID: docker://f8732ac0514ddc25c11625941f619b3d98dbddef4a57eb6f33a37147d3a82c21
Image: wordpress:latest
Image ID: docker-pullable://wordpress@sha256:0524b6843bd9a310c8e7201fd2d624b9db84baf57e65abf6c22426cd09b55426
Port: <none>
Host Port: <none>
State: Running
Started: Sun, 26 Sep 2019 11:20:43 +0200
Ready: True
Restart Count: 0
Requests:
cpu: 100m
Environment:
WORDPRESS_DB_HOST: <set to the key 'WORDPRESS_DB_HOST' of config map 'wordpress-config'> Optional: false
WORDPRESS_DB_USER: <set to the key 'WORDPRESS_DB_USER' of config map 'wordpress-config'> Optional: false
WORDPRESS_DB_NAME: <set to the key 'WORDPRESS_DB_NAME' of config map 'wordpress-config'> Optional: false
WORDPRESS_DB_PASSWORD: <set to the key 'DB_PASSWD' in secret 'wordpress-db'> Optional: false
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-pz6ww (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-pz6ww:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-pz6ww
Optional: false
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events: <none>
If you've followed my deploy guide to GKE, you will probably recognize some of the information here!
Note that nodes aren't listed by kubectl get all
, so let's list them specifically:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
gke-test-cluster-default-pool-7fa0b2b7-pdqm Ready <none> 3d v1.12.8-gke.10
If you describe
a node, you get interesting information about the pods it's hosting and the resources currently in use:
$ kubectl describe node/gke-test-cluster-default-pool-7fa0b2b7-pdqm
... redacted for your brain's sake ...
Non-terminated Pods: (7 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
default wordpress-d74bfbbc4-qg6fl 100m (10%) 0 (0%) 0 (0%) 0 (0%) 3d
kube-system heapster-v1.6.1-6bf7c45b48-qxvz5 63m (6%) 63m (6%) 215840Ki (7%) 215840Ki (7%) 2d
kube-system kube-dns-564d97dc9c-vsvxr 260m (27%) 0 (0%) 110Mi (4%) 170Mi (6%) 3d
kube-system kube-dns-autoscaler-76fcd5f658-xbxnt 20m (2%) 0 (0%) 10Mi (0%) 0 (0%) 2d
kube-system kube-proxy-gke-test-cluster-default-pool-7fa0b2b7-pdqm 100m (10%) 0 (0%) 0 (0%) 0 (0%) 3d
kube-system l7-default-backend-6f8697844f-7sfd5 10m (1%) 10m (1%) 20Mi (0%) 20Mi (0%) 2d
kube-system metrics-server-v0.3.1-5b4d6d8d98-hk2pw 48m (5%) 143m (15%) 105Mi (3%) 355Mi (13%) 2d
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 601m (63%) 216m (22%)
memory 466720Ki (17%) 773920Ki (28%)
You can see I've got 7 pods running on that node: 6 are from the kube-system
namespace, meaning they're not my own pods but services required by Kubernetes or GKE: heapster
and metrics-server
are used for monitoring, kube-dns*
for networking purposes and l7-default-backend
, which is an HTTP load balancing service.
In the default
namespace, there's my wordpress pod.
In terms of resource, you can see that I'm requesting 63% of my node's CPU capacity, and 17% of its memory capacity.
To get a better understanding of requests and limits, check out this post on Google Cloud's blog.
gcloud
: list & describe
The syntax for gcloud
commands is similar to the kubectl
ones: gcloud <module> <type> <list>
and gcloud <module> <type> <describe> <name>
.
The one thing that can be tricky at first, is figuring out what module
you should look into. There are many, so here's a quick rule of thumb: if the resource is specific to GKE, it's going to be container
; else, you should try compute
.
Resource type | Module | List command |
---|---|---|
Cluster | container | gcloud container clusters list |
Node pool | container | gcloud container node-pools list |
Node (the VM instance) | compute | gcloud compute instances list |
With what we've covered so far on this blog, compute
might not seem so important, but that's also where you'll find forwarding-rules
, backend-services
, backend-buckets
and the other resources related to HTTP(S) Load Balancers.
Access your pods
Port forwarding
If you've got a running pod, but it's not exposed via a service, you can still access whatever's running on it using port forwarding.
Let's take the example of my wordpress pod:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
wordpress-d74bfbbc4-qg6fl 1/1 Running 0 3d
$ kubectl port-forward wordpress-d74bfbbc4-qg6fl 8888:80
Forwarding from 127.0.0.1:8888 -> 80
Forwarding from [::1]:8888 -> 80
I can now access my Wordpress instance listening to the port 80 of this pod, by connecting to http://localhost:8888!
Please just take a second to think about what's going on behind the scene of this very simple command 🤯
Note that you can do the same with a deployment instead of a single pod:
$ kubectl port-forward deployment/wordpress 8888:80
SSH into your pod's containers
It might be handy sometimes to get into a running container of your pod, for debug purposes for instance.
Once again kubectl
makes this super easy. You need to know your pod's name, and the name of the container you want to enter. Then it's very similar to what you'd do with Docker:
$ kubectl describe pod/wordpress-d74bfbbc4-qg6fl
Name: wordpress-d74bfbbc4-qg6fl
Namespace: default
...
Containers:
wordpress: <- this is the container's name
...
$ kubectl exec -it wordpress-d74bfbbc4-qg6fl -c wordpress bash
root@wordpress-d74bfbbc4-qg6fl:/var/www/html#
Note that you can omit the container argument (-c wordpress
here): exec
will then run the specified command within the first container in the pod. When it's a single-container pod, that makes things even easier!
Wrapping up
I hope this little tour of gcloud
and kubectl
will help you get started with managing your Kubernetes cluster from the command line!
And if you're into automation, you should know that both commands allow you to get YAML or JSON output, which will be easily processable within your scripts.
Simply add --output=json
or --format=json
to your kubectl
/gcloud
commands!