Allowing user on CentOS to run docker command without sudo

Out of the box for a Docker install on CentOS 7, you have to sudo the docker command to interact with Docker. Per the post-install steps here, create a docker group and add your user to that group:

sudo groupadd docker

sudo usermod -aG docker youruser

Logging off and back on again, you should now be able to run the docker command without sudo.

On CentOS 7 this still didn’t work for me. Following this post, it appeared that docker.sock was owned by root and in the group root:

$ ls -l /var/run/docker.sock

srw-rw---- 1 root root 0 Oct 21 15:42 /var/run/docker.sock

Changing the group ownership:

$ sudo chown root:docker /var/run/docker.sock

$ ls -l /var/run/docker.sock

srw-rw---- 1 root docker 0 Oct 21 15:42 /var/run/docker.sock

After logging back on, now can run docker commands without sudo.

Deploying kubernetes Dashboard to a kubeadm created cluster

Per installations steps here, to deploy the dashboard:

kubectl --kubeconfig ./admin.conf apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

The start the local proxy:

./kubectl --kubeconfig ./admin.conf proxy

Accessing via http://localhost:8001/ui, gives this error:

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "no endpoints available for service \"kubernetes-dashboard\"",
  "reason": "ServiceUnavailable",
  "code": 503
}

Checking what’s currently running with:

./kubectl --kubeconfig ./admin.conf get pods --all-namespaces

Looks like the dashboard app is not happy:

kube-system   kubernetes-dashboard-747c4f7cf-p8blw          0/1       CrashLoopBackOff   22         1h

Checking the logs for the dashboard:

./kubectl --kubeconfig ./admin.conf logs kubernetes-dashboard-747c4f7cf-p8blw --namespace=kube-system

2017/10/19 03:35:51 Error while initializing connection to Kubernetes apiserver. This most likely means that the cluster is misconfigured (e.g., it has invalid apiserver certificates or service accounts configuration) or the –apiserver-host param points to a server that does not exist. Reason: Get https://10.96.0.1:443/version: dial tcp 10.96.0.1:443: getsockopt: no route to host

OK.

I setup my master node using the flannel overlay. I don’t know if this makes any difference or not, but I noticed this article using kubeadm used Weave Net instead. Not knowing how to move forward (and after browsing many posts and tickets on issues with kubeadm with Dashboard), knowing at least that kubadm + Weave Net works for installing dashboard, so I tried this approach instead.

After re-initializing and the adding weave-net, my pods are all started:

$ kubectl get pods –all-namespaces

NAMESPACE     NAME                                          READY     STATUS    RESTARTS   AGE

kube-system   etcd-unknown000c2960f639                      1/1       Running   0          11m

kube-system   kube-apiserver-unknown000c2960f639            1/1       Running   0          11m

kube-system   kube-controller-manager-unknown000c2960f639   1/1       Running   0          11m

kube-system   kube-dns-545bc4bfd4-nhrw7                     3/3       Running   0          12m

kube-system   kube-proxy-cgn45                              1/1       Running   0          4m

kube-system   kube-proxy-dh6jm                              1/1       Running   0          12m

kube-system   kube-proxy-spxm5                              1/1       Running   0          5m

kube-system   kube-scheduler-unknown000c2960f639            1/1       Running   0          11m

kube-system   weave-net-gs8nh                               2/2       Running   0          5m

kube-system   weave-net-jkkql                               2/2       Running   0          4m

kube-system   weave-net-xb4hx                               2/2       Running   0          10m

 

Trying to add the dashboard once more:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

… and, o. m. g. :

$ kubectl get pods –all-namespaces

NAMESPACE     NAME                                          READY     STATUS    RESTARTS   AGE

kube-system   etcd-unknown000c2960f639                      1/1       Running   0          37m

kube-system   kube-apiserver-unknown000c2960f639            1/1       Running   0          37m

kube-system   kube-controller-manager-unknown000c2960f639   1/1       Running   0          37m

kube-system   kube-dns-545bc4bfd4-nhrw7                     3/3       Running   0          38m

kube-system   kube-proxy-cgn45                              1/1       Running   0          30m

kube-system   kube-proxy-dh6jm                              1/1       Running   0          38m

kube-system   kube-proxy-spxm5                              1/1       Running   0          31m

kube-system   kube-scheduler-unknown000c2960f639            1/1       Running   0          37m

kube-system   kubernetes-dashboard-747c4f7cf-jgmgt          1/1       Running   0          4m

kube-system   weave-net-gs8nh                               2/2       Running   0          31m

kube-system   weave-net-jkkql                               2/2       Running   0          30m

kube-system   weave-net-xb4hx                               2/2       Running   0          36m

Starting kubectl proxy and hitting localhost:8001/ui now gives me:

Error: 'malformed HTTP response "\x15\x03\x01\x00\x02\x02"'
Trying to reach: 'http://10.32.0.3:8443/'

Reading here, trying the master node directly:

https://192.168.1.80:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/

gives a different error:

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "services \"https:kubernetes-dashboard:\" is forbidden: User \"system:anonymous\" cannot get services/proxy in the namespace \"kube-system\"",
  "reason": "Forbidden",
  "details": {
    "name": "https:kubernetes-dashboard:",
    "kind": "services"
  },
  "code": 403
}

… but reading further ahead, it seems accessing via the /ui url is not correctly working, you need to access via the url in the docs here,  which says the correct url is:

http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/

and now I get an authentication page:

Time to read ahead on the authentication approaches.

List available tokens with:

kubectl -n kube-system get secret

Using the same token as per the docs (although at this point I’ve honestly no idea what the difference in permissions is for each of the different tokens):

./kubectl --kubeconfig admin.conf -n kube-system describe secret replicaset-controller-token-7tzd5

And then pasting the token value into the authentication dialog gets me logged on! There’s some errors about this token not having access to some features, but at this point I’ve just glad I’ve managed to get this deployed and working!

If you’re intested in the specific versions I’m using, this is deployed to CentOS 7, and kubernetes version:

$ kubectl version

Client Version: version.Info{Major:”1″, Minor:”8″, GitVersion:”v1.8.1″, GitCommit:”f38e43b221d08850172a9a4ea785a86a3ffa3b3a”, GitTreeState:”clean”, BuildDate:”2017-10-11T23:27:35Z”, GoVersion:”go1.8.3″, Compiler:”gc”, Platform:”linux/amd64″}

Server Version: version.Info{Major:”1″, Minor:”8″, GitVersion:”v1.8.1″, GitCommit:”f38e43b221d08850172a9a4ea785a86a3ffa3b3a”, GitTreeState:”clean”, BuildDate:”2017-10-11T23:16:41Z”, GoVersion:”go1.8.3″, Compiler:”gc”, Platform:”linux/amd64″}

Setting up a Kubernetes cluster across 2 virtualized CentOS nodes

tl:dr – I tried installing Kubernetes from scratch on Fedora Atomic hosts, but couldn’t get it working. I captured the steps I went through up until the point where I got stuck, but thinking there has to be an easier way, I found kubeadm and successfully used that to get a cluster up and running on CentOS instead.

If you’re interested in the steps for my first failed attempt then they’re below, otherwise if you’re interested in the steps (and issues and fixes) to get kubeadm setup on CentOS 7, skip down to Attempt 2.

(Failed )Attempt 1: Setting up Kubernetes from scratch on Fedora Atomic

I following the instructions here, but instead of 4 Atomic hosts I created 2 Fedora Atomic VMs on Proxmox. On the first of the VMs, I started a local Docker Registry container:

sudo docker create -p 5000:5000 \
-v /var/lib/local-registry:/var/lib/registry \
-e REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry \
-e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \
--name=local-registry registry:2

Next, I followed the steps to change the SELinux context on the directory that docker created for our persistence volume, and created a systemd unit file to configure a systemd service to start the registry at startup.

Next up, edit /etc/etcd/etcd.conf  file for the ports to listen on:

ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"
ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"

The first line replaced this original line:

ETCD_LISTEN_CLIENT_URLS="http://localhost:2379"

and the second replaced:

ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"

After following the steps to generate the keys, I had to create the /etc/kubernetes/certs, and then copied the generated files below ./pki/ but apart from ca.crt, the other two files were named server.crt and server.key, so I renamed them to match the instructions when copying to the destination:

sudo cp pki/ca.crt /etc/kubernetes/certs
sudo cp pki/issued/server.crt /etc/kubernetes/certs/kubernetes-master.crt
sudo cp pki/private/server.key /etc/kubernetes/certs/kubernetes-master.key

I followed the steps up to the point of starting the kuberetes service, and then got an error:

$ sudo systemctl start etcd kube-apiserver kube-controller-manager kube-scheduler

Job for kube-apiserver.service failed because the control process exited with error code.

See "systemctl  status kube-apiserver.service" and "journalctl  -xe" for details.

Using journalctl -xe to take a look at the logs, I’ve got a * lot * of :

reflector.go:201] k8s.io/kubernetes/pkg/client/informers/informers_generated/externalversions//factory.go:70: Failed to list *v1.ReplicationController: Get http://192.168.1.76:8080/api/v1/replicationcontrollers?resourceVersion=0: dial tcp 192.168.1.76:8080: getsockopt: connection refused

This implies the api server is not running.

This is the point where I started reading around for help, but started to ask after I’d walked through all the manual steps to get this far and hadn’t got it working yet if there’s a better/quicker way to setup Kubernetes. Turns out there is, kubeadm

Successful attempt 2: Setting up a Kubernetes cluster using kubeadm on CentOS 7

Compared to the manual installation and configuration steps, kubeadm looks very attractive as it does a lot of the work for you.

Following the instructions here, the first issue I ran into was this step and this didn’t work for me on CentOS 7:

sudo sysctl net.bridge.bridge-nf-call-iptables=1

sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory

I skipped this (not knowing if there’s something comparable for CentOS) and continued on. Next, install Docker:

yum install -y docker

Enable at boot:

systemctl enable docker && systemctl start docker

Install kubelet, kubeadm and kubectl (this section straight from the docs):

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
        https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
setenforce 0
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet && systemctl start kubelet

Next, use kubeadm to create a cluster. Reading forward in the instructions, to initialize the networking overlay with for example flannel, you also need to pass options to init, so:

kubeadm init --pod-network-cidr=10.244.0.0/16

This gave me some errors about kubelet not yet running, so I missed the step above to enable and start kubelet:

[preflight] Running pre-flight checks
[preflight] WARNING: kubelet service is not enabled, please run 'systemctl enable kubelet.service'
[preflight] WARNING: firewalld is active, please ensure ports [6443 10250] are open or your cluster may not function correctly
[preflight] WARNING: Running with swap on is not supported. Please disable swap or set kubelet's --fail-swap-on flag to false.

One more try:

systemctl enable kubelet && systemctl start kubelet

then again:

kubeadm init --pod-network-cidr=10.244.0.0/16

It seems you can’t run init more than once:

[preflight] Some fatal errors occurred:
 /etc/kubernetes/manifests is not empty
 /var/lib/kubelet is not empty
[preflight] If you know what you are doing, you can skip pre-flight checks with `--skip-preflight-checks`

Per the ‘tear down’ instructions,

kubeadm reset

Then once more time:

kubeadm init --pod-network-cidr=10.244.0.0/16

Next error:

[kubelet-check] It seems like the kubelet isn't running or healthy.
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10255/healthz/syncloop' failed with error: Get http://localhost:10255/healthz/syncloop: dial tcp [::1]:10255: getsockopt: connection refused.

Checking ‘systemctl status kubelet’ shows it failed on startup because swap was still enabled:

kubelet[14829]: error: failed to run Kubelet: Running with swap on is not supported, please disable swap! or set --fail-swap

To disable swap per answers to this question,

swapoff -a

And then I edited /etc/fstab to remove the /dev/mapper/centos-swap line, and then rebooted.

Once more:

kubeadm reset
kubeadm init --pod-network-cidr=10.244.0.0/16

To address the error about opening ports:

[preflight] WARNING: firewalld is active, please ensure ports [6443 10250] are open or your cluster may not function correctly

I opened up the ports with new rules:

sudo firewall-cmd --zone=public --add-port=6443/tcp --permanent
sudo firewall-cmd --zone=public --add-port=10250/tcp --permanent

At this point the cluster starts initializing and I get this message for a several minutes while it’s downloading/initializing:

[init] Waiting for the kubelet to boot up the control plane as Static Pods from directory "/etc/kubernetes/manifests"
[init] This often takes around a minute; or longer if the control plane images have to be pulled.

I waited for several minutes, but it didn’t seem to do anything. Looking in ‘journalctl -xeu kubelet’ there’s many ‘connection refused’ errors repeating over and over:

192.168.1.79:6443/api/v1/nodes: dial tcp 192.168.1.79:6443: getsockopt: connection refused
192.168.1.79:6443/api/v1/services?resourceVersion=0: dial tcp 192.168.1.79:6443: getsockopt: connection refused
192.168.1.79:6443/api/v1/nodes?fieldSelector=metadata.name%3Dunknown0a7dd195e7cb&resourceVersion=0: dial tcp 192.168.1.79:6443: getsockopt: connection refused
192.168.1.79:6443/api/v1/pods?fieldSelector=spec.nodeName%3Dunknown0a7dd195e7cb&resourceVersion=0: dial tcp 192.168.1.79:6443: getsockopt: connection refused
n0a7dd195e7cb.14ebbc48a9463585: dial tcp 192.168.1.79:6443: getsockopt: connection refused' (may retry after sleeping)

Searching for anything similar I came up with these which have similar errors and symptoms:

https://github.com/kubernetes/kubernetes/issues/33729

https://github.com/kubernetes/kubernetes/issues/43815

https://github.com/kubernetes/kubeadm/issues/353

https://github.com/kubernetes/kubernetes/issues/45787

The issue that helped for me though was this one, where in one of the steps to recreate there is a comment:

# edit /etc/selinux/config and set SELINUX=disabled

The kubeadm install steps do state:

“Disabling SELinux by running setenforce 0 is required to allow containers to access the host filesystem”

but in the steps it only mentions runningsetenforce 0

which I’m not sure is the same as editing /etc/selinux/config. I edited the file, set SELINUX=disabled, rebooted, fired up kubeadm init again, and this time we’re in luck!

[init] Waiting for the kubelet to boot up the contr
ol plane as Static Pods from directory "/etc/kubernetes/manifests"

[init] This often takes around a minute; or longer if the control plane images have to be pulled.

[apiclient] All control plane components are healthy after 43.002301 seconds

[uploadconfig] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace

[markmaster] Will mark node unknown0a7dd195e7cb as master by adding a label and a taint

[markmaster] Master unknown0a7dd195e7cb tainted and labelled with key/value: node-role.kubernetes.io/master=""

[bootstraptoken] Using token: xyz

[bootstraptoken] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials

[bootstraptoken] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token

[bootstraptoken] Creating the "cluster-info" ConfigMap in the "kube-public" namespace

[addons] Applied essential addon: kube-dns

[addons] Applied essential addon: kube-proxy

Your Kubernetes master has initialized successfully!

To start using your cluster, you need to run (as a regular user):

  mkdir -p $HOME/.kube

  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.

Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:

  http://kubernetes.io/docs/admin/addons/

You can now join any number of machines by running the following on each node

as root:

  kubeadm join --token xyz --discovery-token-ca-cert-hash sha256:abc

Success!

Following the next steps in the instructions, I set up the config for my regular user:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

And then continuing the steps to add the networking config, for flannel:

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.8.0/Documentation/kube-flannel.yml
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.8.0/Documentation/kube-flannel-rbac.yml

Checking the running pods to confirm we’re up and running: (two ‘-‘ in the param)

[kev@unknown0A7DD195E7CB ~]$ kubectl get pods –all-namespaces

NAMESPACE     NAME                                          READY     STATUS             RESTARTS   AGE

kube-system   etcd-unknown0a7dd195e7cb                      1/1       Running            0          2h

kube-system   kube-apiserver-unknown0a7dd195e7cb            1/1       Running            0          2h

kube-system   kube-controller-manager-unknown0a7dd195e7cb   1/1       Running            0          2h

kube-system   kube-dns-545bc4bfd4-wfs5s                     3/3       Running            0          2h

kube-system   kube-flannel-ds-qtfwh                         1/2       CrashLoopBackOff   4          3m

kube-system   kube-proxy-ggvqx                              1/1       Running            0          2h

kube-system   kube-scheduler-unknown0a7dd195e7cb            1/1       Running            0          2h

Now we’re looking good!

Last step adding an additional node and joining the cluster. Repeating all the steps up until but instead of kubeadm init, run the kubeadm join command passing the token and has values.

Back on the master node, running:

[kev@unknown0A7DD195E7CB ~]$ kubectl get nodes

NAME                  STATUS     ROLES     AGE       VERSION
unknown0a7dd195e7cb   Ready      master    3h        v1.8.0
unknown121e8862fff9   NotReady   <none>    48s       v1.8.0

A few more seconds later:

[kev@unknown0A7DD195E7CB ~]$ kubectl get nodes

NAME                  STATUS    ROLES     AGE       VERSION
unknown0a7dd195e7cb   Ready     master    3h        v1.8.0
unknown121e8862fff9   Ready     <none>    51s       v1.8.0

A 2 node kubernetes cluster, one master and one worker, ready for running some containers!

Running a remote Docker Registry and getting ‘HTTP response to HTTPS request’ error on push

It’s been a while since I looked into running a Docker Registry to host images, my previous notes on setting this up are here. While looking into setting up Docker Registry running on a remote CentOS VM (currently running on my Mac Pro running Proxmox) I ran into the configuration issue with insecure registries.

Having tagged an image ready to push to my remote Repository, this error looks like this:

$ docker push 192.168.1.73:5000/redisservice

The push refers to a repository [192.168.1.73:5000/redisservice]

Get https://192.168.1.73:5000/v2/: http: server gave HTTP response to HTTPS client

Unless you’re familiar with this error and the required flag to configure running a Repository insecure (for local testing), there’s articles and posts about how to configure this, but it’s not immediately obvious that the config need to be made on the client side where you’re trying to push from, not on the server side running the Repository.

On my CentOS server side this would be configured in /etc/docker/daemon.json as:

{
   "insecure-registries": [
     "192.168.1.73:5000"
   ]
}

But after finding this has no effect, I saw this post, which suggested to configure this from the client. From my Mac Docker client this can be configured using the widget in the toolbar when Docker is running:

Now trying again:

$ docker push 192.168.1.73:5000/redisservice

The push refers to a repository [192.168.1.73:5000/redisservice]

2ac8b2b0781d: Pushed 

7ce27e37c9b1: Pushed 

e870224c1375: Pushed 

3fc666989c1d: Pushed 

latest: digest: sha256:9f015c8d73c814d8bf0c0d089b8960c7c5c36cec750c81e09378cd2cb8d844af size: 1159

Success! Next up, I’m looking into creating a Stack of my related Container services on Rancher.