I'm building an application that I will run in GKE. This application will use shell commands (for now) to build docker images and try to push them to GCR. I'm finding that when I try to do this from a pod running in GKE I get authentication problems. I'm having trouble figuring out why these authentication problems are happening.
Here's a list of all of the debugging I've done so far. At the highest level, my GKE clusters have the https://www.googleapis.com/auth/devstorage.read_write oauth scope. When I examine the permissions on the underlying GCE instance, I see these permissions - note the Read Write value for Storage:
Now, when I SSH into that instance using the console and list the docker images I see the image used by GKE when spinning up my pod:
paymahn#gke-prod-478557c-default-pool-e9314f46-d9mn ~ $ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
gcr.io/gadic-310112/server latest 8f8a22237c31 2 days ago 1.85GB
...
However, if I try to manually pull that image while SSH-ed into the GCP instance, I get an authentication problem:
paymahn#gke-prod-478557c-default-pool-e9314f46-d9mn ~ $ docker pull gcr.io/gadic-310112/server:latest
Error response from daemon: unauthorized: You don't have the needed permissions to perform this operation, and you may have invalid credentials. To authenticate your request, follow the steps in: https://cloud.google.com/container-registry/docs/advanced-authentication
I also looked at the service account 65106360748-compute#developer.gserviceaccount.com which is the default compute instance service account. Here are the permissions it has (I manually added the Storage Object Creator role):
Adding the Storage Object Creator role to that service account didn't help.
Is my approach to authentication here fundamentally flawed? It seems like I have all the right pieces in place to pull/push from GCR from GKE. Maybe there's an extra step I need to do for the docker client to authenticate?
Figured it out. I had to:
make a service account with the roles/storage.objectAdmin
generate a key for that service account
store that key as a secret in GKE
Mount that secret into my pods
run gcloud auth activate-service-account --key-file <path to key>
run gcloud auth configure-docker
Once all of that was done, my pods could pull from and push to GCR.
Related
I'm not able to push docker images from Compute Engine VM to Container registry. I have added the credentials to the service account but I still get:
unauthorized: You don't have the needed permissions to perform this operation, and you may have invalid credentials. To authenticate your request, follow the steps in: https://cloud.google.com/container-registry/docs/advanced-authentication
Your service account should have roles/storage.legacyBucketWriter role on GCR's bucket (artifacts.PROJECT-ID.appspot.com for gcr.io). More documentation is here.
In order to deploy an application using docker and a remote registry:
Using docker client, execute docker login so that the credentials will be stored either directly in $HOME/.docker/config.json or on a credential store specified also in $HOME/.docker/config.json. Then use the docker create command to start the application.
In kubernetes, a secret can be generated using the docker registry username and password. Then, the secret can be injected in the helm-chart using imagePullSecret. then, helm install command can instruct kubelet to pull the image inside the created container inside the scheduled pod. To update the image registry, the image name and pull secret can be updated before re-installation.
I have three questions:
How can I set the username and password or inject these credentials for the services in docker-compose without having to run docker login first in each deployment host ? (as in nu
Can I populate a credential store specified in a $HOME/.docker/config.json using docker login command on one machine, then specify the same credential store in $HOME/.docker/config.json of another machine, then use the answer of the previous question to inject or pull the credentials
if the docker daemon checks for the credentials inside the credential stores that is specified in $HOME/.docker/config.json, then what is the use of the helper program ?
Since Docker Hub only allows 1 private repo, I wonder if there is any way to use Github or Gitlab, etc., to download the images? for instance:
FROM git#github.com/username/repo
...
...
...
Very easy with an account on gitlab.com. GitLab provides a Docker registry linked to projects and you can have unlimited private projects:
Create a project my-docker-project
Go to Package and Registries > Container registries, you should see a few commands to access your registry
Connect your machine to this registry using a command like:
# Will prompt for login/pass
docker login registry.gitlab.com
You'll need an access token or deploy token with read_registry and write_registry scopes. You can generate one via your profile Preferences > Access token. Login is the token name and password the secret token provided.
You can now push Docker images with commands such as:
# Push an image
docker push registry.gitlab.com/YourUsernameOrGroup/my-docker-project
# Push an image on a sub-path
docker push registry.gitlab.com/YourUsernameOrGroup/my-docker-project/myimage
You can then use the image in a Dockerfile by referencing its URL such as:
FROM registry.gitlab.com/YourUsernameOrGroup/my-docker-project
# ...
Of course the machine from which you build must be authenticated on related GitLab registry using docker login command above (or the project must be public)
both have excellent package registry services
For GitHub GPR
For GitLab GCR
Both have excellent features like use it directly from Dockerfile as you want for example.
I have a public example, you can check it in Github with node.js which uses GPR to store the build image/package.
We are using the Google Container Registry to store our Docker images.
To authorize our build instances we place long-lived access tokens in .docker/config.json as described in the docs.
This works perfectly fine until someone (i.e. some Makefile) uses gcloud docker -- push ... to push to the registry (instead of e.g. docker push ...). gcloud will replace the existing, long-lived credentials with short-lived ones that expire after some time. Thus subsequent builds may fail, depending on the exact timing.
My Question: How can I prevent gcloud docker ... from messing with my provisioned credentials?
I've tried chattr +i .docker/config.json, but this just makes gcloud complain.
From https://cloud.google.com/sdk/gcloud/reference/docker:
The gcloud docker command group wraps docker commands, so that gcloud can inject the appropriate fresh authentication token into requests that interact with the docker registry.
The only thing that gcloud docker does is change these credentials, then invoke the docker CLI. If you don't want it to change the credentials, there's no reason not to just call docker directly.
One workaround might be to use an alternate configuration file location for your long-lived credentials; per https://docs.docker.com/engine/reference/commandline/cli/:
Options:
--config string Location of client config files (default "/root/.docker")
I've set up an OpenShift Origin 1.1.3 cluster. Now I'm pulling images from a private registry. This registry is 'insecure'. It has self-signed certificates and credentials to authenticate. I'm able to perform a docker login and to pull the image manually on my node.
The problem is that only that node can access the image. So when I'm scaling my pod (based on that image), all replica's will run on that specific node. Other nodes are not able to pull or use the image.
So I want to create an image-stream for my image:
oc import-image --insecure=true ec2-xxx:5000/image
But: message: you may not have access to the Docker image "ec2-xxx:5000/image"
reason: Unauthorized
I read about creating a secret. I created it:
oc secrets new-dockercfg mysecret --docker-server=ec2-xxx:5000 --docker-username=*** --docker-password=*** --docker-email=any#mail.com
How do I have to add this secret to my image-stream? And is this the right approach?
#cloudnoob his answer helped me a lot.
But the main problem was that I've created my secret in the wrong way.
I saw this after starting the OpenShift master with loglevel 5.
Unable to find a secret to match https://ec2-xxx:5000/v2/test/image/manifests/83
So I had to create my secret with https (it's called insecure with selfsigned certificates but it's using https):
oc secrets new-dockercfg mysecret --docker-server=https://ec2-xxx:5000 --docker-username=*** --docker-password=*** --docker-email=any#mail.com
After this step I had to perform the steps of cloudnoob. Adding the secrets to the service accounts. After that the import is a succes.
Openshift Origin Doc
To use a secret for pulling images for pods, you must add the secret to your service account. The name of the service account in this example should match the name of the service account the pod will use; default is the default service account:
$ oc secrets add serviceaccount/default secrets/ --for=pull
To use a secret for pushing and pulling build images, the secret must be mountable inside of a pod. You can do this by running:
$ oc secrets add serviceaccount/builder secrets/