Your personal #Kubernetes image repo in a few steps (gcr.io)

Hello there.

Yep! K8s is giving my some nosleep. New challenge: use my own images could be a bit more harder that I’ve thought. Then, I’ve decided to use gcr.io (for now). There’re some info you can get from Kubernetes: Hello World Walkthrough However, I want to use my own private cluster. That brings a bit more challenge.

First of all, get your k8s up and running. You can follow this steps to get one from scratch.

Activate your Google Cloud Platform account

Don’t worry, tell you later how to create your own private registry. If you don’t already have a Google Account (Gmail or Google Apps), you must create one. Then, sign-in to Google Cloud Platform console (console.cloud.google.com) and create a new project.

Don’t forget to activate your “Billing” (just a trial of 60 days. don’t be greedy)

k8s-personal-repo-gcr-io-gcloud-signup-console-01

Create your new project. Mine is called “k8s-helloworld-142719”

k8s-personal-repo-gcr-io-gcloud-signup-console-02

Important: make sure the Compute Engine API is enabled for your project on the https://console.developers.google.com/apis page. Took me while to figure it out that. If you don’t do that you will get this message trying to push your image: “denied: Unable to create the repository, please check that you have access to do so.”

[root@master ~]# gcloud docker push gcr.io/k8s-helloworld-142719/hello-node:v1
The push refers to a repository [gcr.io/k8s-helloworld-142719/hello-node]
62226d458511: Preparing 
20a6f9d228c0: Preparing 
80c332ac5101: Preparing 
04dc8c446a38: Preparing 
1050aff7cfff: Preparing 
66d8e5ee400c: Waiting 
2f71b45e4e25: Waiting 
denied: Unable to create the repository, please check that you have access to do so.

Install gsutil

You can follow this instructions Google Cloud Docs: Install gsutil
Don’t forget to set your PROJECT_ID env. My case I did:

export PROJECT_ID="k8s-helloworld-142719"
curl https://sdk.cloud.google.com | bash
exec -l $SHELL
gcloud init

This is my last part of the setup from the console:

[root@master ~]# gcloud init
Welcome! This command will take you through the configuration of gcloud.

Your current configuration has been set to: [default]

Network diagnostic detects and fixes local network connection issues.
Checking network connection...done.                                                                                                                                       
Reachability Check passed.
Network diagnostic (1/1 checks) passed.

You must log in to continue. Would you like to log in (Y/n)?  Y

Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&prompt=select_account&response_type=code&client_id=9999999999.apps.googleusercontent.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcompute&access_type=offline


Enter verification code: 4/Qec-coYeOCXXXXXXXXXXXXXXXXXXXX9ITT5sSfUE
You are logged in as: [xoxoxoxo@gmail.com].

Your current project has been set to: [k8s-helloworld-142719].

Not setting default zone/region (this feature makes it easier to use
[gcloud compute] by setting an appropriate default value for the
--zone and --region flag).
See https://cloud.google.com/compute/docs/gcloud-compute section on how to set
default compute region and zone manually. If you would like [gcloud init] to be
able to do this for you the next time you run it, make sure the
Compute Engine API is enabled for your project on the
https://console.developers.google.com/apis page.

Created a default .boto configuration file at [/root/.boto]. See this file and
[https://cloud.google.com/storage/docs/gsutil/commands/config] for more
information about configuring Google Cloud Storage.
Your Google Cloud SDK is configured and ready to use!

* Commands that require authentication will use pinrojas@gmail.com by default
* Commands will reference project `k8s-helloworld-142719` by default
Run `gcloud help config` to learn how to change individual settings

This gcloud configuration is called [default]. You can create additional configurations if you work with multiple accounts and/or projects.
Run `gcloud topic configurations` to learn more.

Some things to try next:

* Run `gcloud --help` to see the Cloud Platform services you can interact with. And run `gcloud help COMMAND` to get help on any gcloud command.
* Run `gcloud topic -h` to learn about advanced features of the SDK like arg files and output formatting

IMPORTANT: DO THAT IN EVERY K8S NODE TO HAVE ACCESS TO YOUR REPO. IF YOU DON’T HAVE ACCESS YOU WILL RECEIVE A MESSAGE LIKE THIS:

[root@minion02 ~]# docker pull gcr.io/k8s-helloworld-142719/hello-node:v1
Trying to pull repository gcr.io/k8s-helloworld-142719/hello-node ... 
Pulling repository gcr.io/k8s-helloworld-142719/hello-node
Error: Status 403 trying to pull repository k8s-helloworld-142719/hello-node: "Unable to access the repository: k8s-helloworld-142719/hello-node; please verify that it exists and you have permission to access it (no valid credential was supplied)."

All set to start building and pushing images

Create and build you image

Do the following from your home folder (BTW, I am using root):

mkdir ~/hello
cd ~/hello
cat << 'EOF' >> Dockerfile
FROM node:4.4
EXPOSE 8080
COPY server.js .
CMD node server.js
EOF
cat << 'EOF' >> server.js
var http = require('http');
var handleRequest = function(request, response) {
  console.log('Received request for URL: ' + request.url);
  response.writeHead(200);
  response.end('Hello World version ONE! Host/Pod: ' + process.env.HOSTNAME + '\n');
};
var www = http.createServer(handleRequest);
www.listen(8080);
EOF

Check out your Dockerfile and server.js files. Now let’s create out first image. Execute

docker build -t gcr.io/k8s-helloworld-142719/hello-node:v1 .

You will se something like this:

[root@master hello]# docker build -t gcr.io/k8s-helloworld-142719/hello-node:v1 .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM node:4.4
Trying to pull repository docker.io/library/node ... 
4.4: Pulling from docker.io/library/node

357ea8c3d80b: Pull complete 
52befadefd24: Pull complete 
3c0732d5313c: Pull complete 
ceb711c7e301: Pull complete 
868b1d0e2aad: Pull complete 
3a438db159a5: Pull complete 
Digest: sha256:e720e944ce6994a461cd2a9e0ae34c4bc45c0f9ee7b3f48052933182fc5f0bf1
Status: Downloaded newer image for docker.io/node:4.4
 ---> 93b396996a16
Step 2 : EXPOSE 8080
 ---> Running in 2c090e93a888
 ---> aba5143017b7
Removing intermediate container 2c090e93a888
Step 3 : COPY server.js .
 ---> a1b43afe34b9
Removing intermediate container 480a6963b8ec
Step 4 : CMD node server.js
 ---> Running in f4a24f3c527c
 ---> 828ed86702d7
Removing intermediate container f4a24f3c527c
Successfully built 828ed86702d7

Let’s test it (I’ve used port 8081. My server was already using 8080):

docker run -d -p 8081:8080 --name hello_tutorial gcr.io/k8s-helloworld-142719/hello-node:v1
curl http://localhost:8081

You will see something like this:

[root@master hello]# docker run -d -p 8081:8080 --name hello_tutorial gcr.io/k8s-helloworld-142719/hello-node:v1
8d179fbe6f79d84e853311bc238c822e0567f973315b875cd50241236bde593e
[root@master hello]# curl http://localhost:8081
Hello World version ONE! Host/Podhello-node-3439300230-bg6ew

It’s time to push your image

gcloud docker push gcr.io/k8s-helloworld-142719/hello-node:v1

You will see something like this

[root@master ~]# gcloud docker push gcr.io/k8s-helloworld-142719/hello-node:v1
The push refers to a repository [gcr.io/k8s-helloworld-142719/hello-node]
62226d458511: Pushed 
20a6f9d228c0: Pushed 
80c332ac5101: Pushed 
04dc8c446a38: Pushed 
1050aff7cfff: Pushed 
66d8e5ee400c: Pushed 
2f71b45e4e25: Pushed 
v1: digest: sha256:5ee9b961a56fea7604f62a8d7bba913681ad1b8b3756c7848ea69794e4f0c79a size: 9399

All set to create your first deployment:

kubectl run hello-node --image=gcr.io/k8s-helloworld-142719/hello-node:v1 --replicas=4 --port=8080

And you’ll get this:

[root@master hello]# kubectl run hello-node --image=gcr.io/k8s-helloworld-142719/hello-node:v1 --replicas=4 --port=8080
deployment "hello-node" created
[root@master hello]# kubectl get all
NAME                          CLUSTER-IP   EXTERNAL-IP         PORT(S)    AGE
kubernetes                    10.254.0.1   <none>              443/TCP    51d
NAME                          READY        STATUS              RESTARTS   AGE
hello-node-3439300230-bg6ew   0/1          ContainerCreating   0          8s
hello-node-3439300230-or7r0   0/1          ContainerCreating   0          8s
hello-node-3439300230-w4qeg   0/1          ContainerCreating   0          8s
hello-node-3439300230-wdbey   0/1          ContainerCreating   0          8s
[root@master hello]# kubectl get all
NAME                          CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes                    10.254.0.1   <none>        443/TCP    51d
NAME                          READY        STATUS        RESTARTS   AGE
hello-node-3439300230-bg6ew   1/1          Running       0          1m
hello-node-3439300230-or7r0   1/1          Running       0          1m
hello-node-3439300230-w4qeg   1/1          Running       0          1m
hello-node-3439300230-wdbey   1/1          Running       0          1m
[root@master hello]# kubectl expose deployment hello-node --type="LoadBalancer"
service "hello-node" exposed
[root@master hello]# kubectl get all
NAME                          CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
hello-node                    10.254.222.1                 8080/TCP   7s
kubernetes                    10.254.0.1     <none>        443/TCP    51d
NAME                          READY          STATUS        RESTARTS   AGE
hello-node-3439300230-bg6ew   1/1            Running       0          1m
hello-node-3439300230-or7r0   1/1            Running       0          1m
hello-node-3439300230-w4qeg   1/1            Running       0          1m
hello-node-3439300230-wdbey   1/1            Running       0          1m

I have create a tiny script to check my app:

cat << 'EOF' >> 0_curl_test.sh 
while true
do
 curl http://10.254.222.1:8080
 sleep 1
done
EOF
chmod 755 0_curl_test.sh

You will get this:

[root@minion02 ~]# ./0_curl_test.sh 
Hello World version ONE! Host/Podhello-node-3439300230-bg6ew
Hello World version ONE! Host/Podhello-node-3439300230-bg6ew
Hello World version ONE! Host/Podhello-node-3439300230-w4qeg
Hello World version ONE! Host/Podhello-node-3439300230-bg6ew
Hello World version ONE! Host/Podhello-node-3439300230-or7r0
Hello World version ONE! Host/Podhello-node-3439300230-wdbey
Hello World version ONE! Host/Podhello-node-3439300230-w4qeg
Hello World version ONE! Host/Podhello-node-3439300230-or7r0
Hello World version ONE! Host/Podhello-node-3439300230-bg6ew

Check this video from Burr Sutter: Docker+Kubernetes+OpenShift Demo
This will give more ideas.

See ya!

One thought on “Your personal #Kubernetes image repo in a few steps (gcr.io)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s