802.11ac on Linux With NetGear A6100 (RTL8811AU) USB Adapter

NOTE: Most of the content from this post comes from a blog post I found that concentrated on getting the driver set up on Fedora 21. I did mostly the same steps with a few tweaks.

Intro

Driver support for 802.11ac in Linux is spotty especially if you are using a USB adapter. I picked up the NetGear A6100 that has the Realtek RTL8811AU chip inside of it. Of course, when I plug it in I can see the device, but no support in the kernel I'm using (kernel-4.2.8-200.fc22.x86_64).

On my system I currently have the built in wireless adapter, as well as the USB plugged in. From the output below you can see only one wireless NIC shows up:

# lspci | grep Network
00:19.0 Ethernet controller: Intel Corporation 82579LM Gigabit Network Connection (rev 04)
03:00.0 Network controller: Intel Corporation Centrino Ultimate-N 6300 (rev 3e)
$ lsusb | grep NetGear
Bus 001 Device 002: ID 0846:9052 NetGear, Inc. A6100 AC600 DB Wireless Adapter [Realtek RTL8811AU]
# ip -o link | grep wlp | cut -d ' ' -f 2
wlp3s0:

The wlp3s0 is my built in wifi device.

The Realtek Driver

You can find the Realtek driver for the RTL8811AU at a couple of the sites for the many vendors that incorporate the chip:

These drivers often vary in version and often don't compile on newer kernels, which can be frustrating when you just want something to work.

Getting The RTL8811AU Driver Working

Luckily some people in the community unofficially manage code repositories with fixes to the Realtek driver to allow it to compile on newer kernels. From the blog post I mentioned earlier there is a linked GitHub repository where the Realtek driver is reproduced with some patches on top. This repository makes it pretty easy to get set up and get the USB adapters working on Linux.

NOTE: In case the git repo moves in the future I have copied an archive of it here for posterity. The commit id at head at the time of this use is 9fc227c2987f23a6b2eeedf222526973ed7a9d63.

The first step is to set up your system for DKMS to make it so that you don't have to recompile the kernel module every time you install a new kernel. To do this install the following packages and set the dkms service to start on boot:

# dnf install -y dkms kernel-devel-$(uname -r)
# systemctl enable dkms

Next, clone the git repository and observe the version of the driver:

# mkdir /tmp/rtldriver && cd /tmp/rtldriver
# git clone https://github.com/Grawp/rtl8812au_rtl8821au.git
# cat rtl8812au_rtl8821au/include/rtw_version.h 
#define DRIVERVERSION   "v4.3.14_13455.20150212_BTCOEX20150128-51"
#define BTCOEXVERSION   "BTCOEX20150128-51"

From the output we can see this is the 4.3.14_13455.20150212 version of the driver, which is fairly recent.

Next let's create a directory under /usr/src for the source code to live and copy it into place:

# mkdir /usr/src/8812au-4.3.14_13455.20150212
# cp -R  ./rtl8812au_rtl8821au/* /usr/src/8812au-4.3.14_13455.20150212/

Next we'll create a dkms.conf file which will tell DKMS how to manage building this module when builds/installs are requested; run man dkms to view more information on these settings:

# cat <<'EOF' > /usr/src/8812au-4.3.14_13455.20150212/dkms.conf
PACKAGE_NAME="8812au"
PACKAGE_VERSION="4.3.14_13455.20150212"
BUILT_MODULE_NAME[0]="8812au"
DEST_MODULE_LOCATION[0]="/kernel/drivers/net/wireless"
AUTOINSTALL="yes"
MAKE[0]="'make' all KVER=${kernelver}"
CLEAN="'make' clean"
EOF

Note one change from the earlier blog post, which is that I include KVER=${kernelver} in the make line. If you don't do this then the Makefile will incorrectly detect the kernel by calling uname, which is wrong when run during a new kernel installation because the new kernel is not yet running. If we didn't do this then every time a new kernel was installed the driver would get compiled for the previous kernel (the one that was running at the time of installation).

The next step is to add the module to the DKMS system and go ahead and build it:

# dkms add -m 8812au -v 4.3.14_13455.20150212

Creating symlink /var/lib/dkms/8812au/4.3.14_13455.20150212/source ->
                 /usr/src/8812au-4.3.14_13455.20150212

DKMS: add completed.
# dkms build -m 8812au -v 4.3.14_13455.20150212

Kernel preparation unnecessary for this kernel.  Skipping...

Building module:
cleaning build area...
'make' all KVER=4.2.8-200.fc22.x86_64......................
cleaning build area...

DKMS: build completed.

And finally install it:

# dkms install -m 8812au -v 4.3.14_13455.20150212

8812au:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/4.2.8-200.fc22.x86_64/extra/
Adding any weak-modules

depmod....

DKMS: install completed.

Now we can load the module and see information about it:

# modprobe 8812au
# modinfo 8812au | head -n 3
filename:       /lib/modules/4.2.8-200.fc22.x86_64/extra/8812au.ko
version:        v4.3.14_13455.20150212_BTCOEX20150128-51
author:         Realtek Semiconductor Corp.

Does the wireless NIC work now? After connecting to an AC only network here are the results:

# ip -o link | grep wlp | cut -d ' ' -f 2
wlp3s0:
wlp0s20u2:
# iwconfig wlp0s20u2
wlp0s20u2  IEEE 802.11AC  ESSID:"random"  Nickname:"<WIFI@REALTEK>"
          Mode:Managed  Frequency:5.26 GHz  Access Point: A8:BB:B7:EE:B6:8D   
          Bit Rate:87 Mb/s   Sensitivity:0/0  
          Retry:off   RTS thr:off   Fragment thr:off
          Encryption key:****-****-****-****-****-****-****-****   Security mode:open
          Power Management:off
          Link Quality=95/100  Signal level=100/100  Noise level=0/100
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0

Sweet!!

Keeping it Working After Kernel Updates

Let's test out to see if updating a kernel leaves us with a system that has an updated driver or not. Before the kernel update:

# tree /var/lib/dkms/8812au/4.3.14_13455.20150212/
/var/lib/dkms/8812au/4.3.14_13455.20150212/
├── 4.2.8-200.fc22.x86_64
│   └── x86_64
│       ├── log
│       │   └── make.log
│       └── module
│           └── 8812au.ko
└── source -> /usr/src/8812au-4.3.14_13455.20150212

5 directories, 2 files

Now the kernel update and viewing it after:

# dnf -y update kernel kernel-devel --enablerepo=updates-testing
...
Installed:
  kernel.x86_64 4.3.3-200.fc22
  kernel-core.x86_64 4.3.3-200.fc22
  kernel-devel.x86_64 4.3.3-200.fc22
  kernel-modules.x86_64 4.3.3-200.fc22

Complete!
# tree /var/lib/dkms/8812au/4.3.14_13455.20150212/
/var/lib/dkms/8812au/4.3.14_13455.20150212/
├── 4.2.8-200.fc22.x86_64
│   └── x86_64
│       ├── log
│       │   └── make.log
│       └── module
│           └── 8812au.ko
├── 4.3.3-200.fc22.x86_64
│   └── x86_64
│       ├── log
│       │   └── make.log
│       └── module
│           └── 8812au.ko
└── source -> /usr/src/8812au-4.3.14_13455.20150212

9 directories, 4 files

And from the log we can verify that the module was built against the right kernel:

# head -n 4 /var/lib/dkms/8812au/4.3.14_13455.20150212/4.3.3-200.fc22.x86_64/x86_64/log/make.log
DKMS make.log for 8812au-4.3.14_13455.20150212 for kernel 4.3.3-200.fc22.x86_64 (x86_64)
Sun Jan 24 19:40:51 EST 2016
make ARCH=x86_64 CROSS_COMPILE= -C /lib/modules/4.3.3-200.fc22.x86_64/build M=/var/lib/dkms/8812au/4.3.14_13455.20150212/build  modules
make[1]: Entering directory '/usr/src/kernels/4.3.3-200.fc22.x86_64'

Success!

The CentOS CI Infrastructure: A Getting Started Guide

Background

The CentOS community is trying to build an ecosystem that fosters and encourages upstream communities to continuously perform integration testing of their code running on the the CentOS platform. The CentOS community has built out an infrastructure that (currently) contains 256 servers ("bare metal" servers") that are pooled together to run tests that are orchestrated by a frontend Jenkins instance located at ci.centos.org.

Who Can Use the CentOS CI?

The CentOS CI is primarily targeted at Open Source projects that use CentOS as a platform in some way. If your project meets those two requirements then check out our page for Getting Started and look at the "Asking for your project to be added" section.

What Is Unique About the CentOS CI?

With many test infrastructures that exist today you are given a virtual machine. With the CentOS CI, when you get a test machine you are actually getting a "bare metal" machine, which allows for testing of workloads that may have not been possible otherwise. One specific example of this is testing out virtualization workloads. The RDO and libvirt projects both use the CentOS CI to do testing that wouldn't be possible on an infrastructure that didn't provide bare metal.

The CentOS CI also offers early access to content that will be in a coming release of CentOS. If there is a pending release, then the content will be available for testing in the CI infrastructure. This allows projects to do testing and find bugs early (before release).

I Have Access. Now What?

Credentials/Environment

Now that you have access to the CentOS CI you should have a few things:

  • Username/Password for the ci.centos.org Jenkins frontend
  • An API key to use with Duffy
  • A target slave type to be used for your testing

The 2nd item from above is unique. In order to provision the bare metal machines and present them for testing, the CentOS CI uses a service known as Duffy (a REST API). The Jenkins jobs that run must provision machines using Duffy and then execute tests on those machines; in the future there may be a Jenkins plugin that takes care of this for you.

The 3rd item is actually specific to your project. The slave machines that are contacted from Jenkins have a workspace set up (like a home directory) for your project. These slaves are accessible via SSH and you can put whatever files you need here in order to orchestrate your tests. When a command is executed in a Jenkins job, these machines are the ones that it is run on.

What you really want, however, is to run tests on the Duffy instances. For that reason the slave is typically just used to request an instance from Duffy and then ssh into the instance to execute tests.

A Test To Run

Even though we've brought the infrastructure together we still need you to write the tests! Basically the requirement here is that you have a git repo that can be cloned on the Duffy instance and then a command to run to kick off the tests.

A very simple example of this is my centos-ci-example repo on GitHub. In this repo the run_tests.sh script executes tests. So for our case we will use the following environment varialbes when defining our Jenkins job below:

GIT_REPO_URL=https://github.com/dustymabe/centos-ci-example
TEST_CMD='./run_tests.sh'

Your First Job: Web Interface

So you have access and you have a git repo that contains a test to run. With the username/password you can login to ci.centos.org and create a new job. To create a new job select New Item from the menu on the left hand side of the screen. Enter a name for your job and Freestyle Project as shown below:

image

After clicking OK, the next page that appears is the page for configuring your job. The following items need to be filled in:

  • Check Restrict where this project can be run
    • Enter the label that applies to environment set up for you

As you can see below, for me this was the atomicapp-shared label.

image

  • Check Inject environment variables to the build process under Build Environment
    • Populate the environment variables as shown below:

image

  • Click on the Add Build Step Dropdown and Select Execute Python Script

image

  • Populate a python script in the text box
    • This script will be executed on the jenkins slaves
    • It will provision new machines using Duffy and then execute the test(s).
    • This script can be found on GitHub or here

image

Now you are all done configuring your job for the first time. There are plenty of more options that Jenkins gives you, but for now click Save and then run the job. You can do this by clicking Build Now and then viwing the output by selecting Console Output as shown in the screenshot below:

image

Your Next Job: Jenkins Job Builder

All of those steps can be done in a more automated fashion by using Jenkins Job Builder. You must install the jenkins-jobs executable for this and create a config file that holds the credentials to interface with Jenkins:

# yum install -y /usr/bin/jenkins-jobs
# cat <<EOF > jenkins_jobs.ini
[jenkins]
user=username
password=password
url=https://ci.centos.org
EOF

Update the file to have the real user/password in it.

Next you must create a job description:

# cat <<EOF >job.yaml
- job:
    name: dusty-ci-example
    node: atomicapp-shared
    builders:
        - inject:
            properties-content: |
                API_KEY=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
                MACHINE_COUNT=1
                TEST_CMD='./run_tests.sh'
                GIT_REPO_URL='https://github.com/dustymabe/centos-ci-example.git'
        - centos-ci-bootstrap
- builder:
    name: centos-ci-bootstrap
    builders:
        - python:
            !include-raw: './run.py'
EOF

Update the file to have the real API_KEY.

The last component is run.py, which is the python script we pasted in before:

# curl http://dustymabe.com/content/2016-01-23/run.py > run.py

Now you can run jenkins-jobs and update the job:

# jenkins-jobs --conf jenkins_jobs.ini update job.yaml
INFO:root:Updating jobs in ['job.yaml'] ([])
INFO:jenkins_jobs.local_yaml:Including file './run.py' from path '.'
INFO:jenkins_jobs.builder:Number of jobs generated:  1
INFO:jenkins_jobs.builder:Reconfiguring jenkins job dusty-ci-example
INFO:root:Number of jobs updated: 1
INFO:jenkins_jobs.builder:Cache saved

NOTE: This is all reproduced in the centos-ci-example jjb directory. Cloning the repo and executing the files from there may be a little easier than running the commands above.

After executing all of the steps you should now be able to execute Build Now on the job, just as before. Take Jenkins Job Builder for a spin and consider it a useful tool when managing your Jenkins jobs.

Conclusion

Hopefully by now you can set up and execute a basic test on the CentOS CI. Come and join our community and help us build out the infrastructure and the feature set. Check out the CI Wiki, send us a mail on the mailing list or ping us on #centos-devel in Freenode.

Happy Testing!
Dusty

Running Nulecules in Openshift via oc new-app

Intro

As part of the Container Tools team at Red Hat I'd like to highlight a feature of Atomic App: support for execution via OpenShift's cli command oc new-app.

The native support for launching Nulecules means that OpenShift users can easily pull from a library of Atomic Apps (Nuleculized applications) that exist in a Docker registry and launch them into OpenShift. Applications that have been packaged up in a Nulecule offer a benefit to the packager and to the deployer of the application. The packager can deliver one Nulecule to all users that supports many different platforms and the deployer gets a simplified delivery mechanism; deploying a Nulecule via Atomic App is easier than trying to manage provider definitions.

DEMO Time

OK. Let's do a demo. I'll choose the guestbook example application developed by Kubernetes. The Nulecule defintion for this example lives here. To start the container in OpenShift via oc new-app you simply run the following command from the command line:

# oc new-app projectatomic/guestbookgo-atomicapp --grant-install-rights

This will run a pod using the container image projectatomic/guestbookgo-atomicapp. The Atomic App software that runs inside the container image will evaluate the Nulecule in the image and communicate with OpenShift in order to bring up the guestbook application, which also leverages redis.

You should now be able to see the redis and guestbook replication controllers and services:

# oc get rc
CONTROLLER     CONTAINER(S)   IMAGE(S)                  SELECTOR                REPLICAS   AGE
guestbook      guestbook      kubernetes/guestbook:v2   app=guestbook           3          3m
redis-master   redis-master   centos/redis              app=redis,role=master   1          3m
redis-slave    redis-slave    centos/redis              app=redis,role=slave    2          3m
# oc get svc
NAME           CLUSTER_IP      EXTERNAL_IP   PORT(S)    SELECTOR                AGE
guestbook      172.30.24.168                 3000/TCP   app=guestbook           3m
redis-master   172.30.210.63   <none>        6379/TCP   app=redis,role=master   3m
redis-slave    172.30.62.63    <none>        6379/TCP   app=redis,role=slave    3m

As well as the pods that are started as a result of the replication controllers:

# oc get pods
NAME                 READY     STATUS    RESTARTS   AGE
guestbook-6gujf      1/1       Running   0          3m
guestbook-m61vq      1/1       Running   0          3m
guestbook-otoz4      1/1       Running   0          3m
redis-master-wdl80   1/1       Running   0          3m
redis-slave-fbapw    1/1       Running   0          3m
redis-slave-oizwb    1/1       Running   0          3m

If you have access to the instance where the pods are running you can access it via a Node IP and NodePort, however this is not common in a hosted environment. In a hosted environment you need to expose the service in openshift via a route:

# oc expose service guestbook
route "guestbook" exposed
# oc get route guestbook
NAME        HOST/PORT                                       PATH      SERVICE     LABELS          INSECURE POLICY   TLS TERMINATION
guestbook   guestbook-proj1.e8ca.engint.openshiftapps.com             guestbook   app=guestbook

Now you should be able to access the guestbook service via the provided hostname; in this case it is guestbook-proj1.e8ca.engint.openshiftapps.com. A quick visit with Firefox gives us:

image

And we have a guestbook up and running!

Give oc new-app on an Atomic App a spin and give us some feeback at .

Dusty

Archived-At Email Header From Mailman 3 Lists

By now most Fedora email lists have been migrated to Mailman3. One little (but killer) new feature that I recently discovered was that Mailman3 includes the RFC 5064 Archived-At header in the emails.

This is a feature I have wanted for a really long time; to be able to find an email in your Inbox and copy and paste a link to anyone without having to find the message in the online archive is going to save a lot of time and decrease some latency when chatting on IRC or some other form of real time communication.

OK, how do I easily get this information out of the header and use it without having to view the email source every time?

I use Thunderbird for most of my email viewing (sometimes mutt for composing). In Thunderbird there is the Archived-At plugin. After installing this plugin you can right click on any message from a capable mailing list and select "Copy Archived-At URL".

Now you are off to share that URL with friends :)

Happy New Year!
Dusty

Fedora Cloud Vagrant Boxes in Atlas

Cross posted with this fedora magazine post

Since the release of Fedora 22, Fedora began creating Vagrant boxes for cloud images in order to make it easier to set up a local environment for development or testing. In the Fedora 22 release cycle we worked out quite a few kinks and we are again releasing libvirt and virtualbox Vagrant boxes for Fedora 23.

Additionally, for Fedora 23, we are making it easier for the users to grab these boxes by having them indexed in Hashicorp's Atlas. Atlas is essentially an index of Vagrant boxes that makes it easy to distribute them (think of it like a Docker registry for virtual machine images). By indexing the Fedora boxes in Atlas, users now have the option of using the vagrant software to download and add the boxes automatically, rather than the user having to go grab the boxes directly from the mirrors first (although this is still an option).

In order to get started with the Fedora cloud base image, run the following command:

# vagrant init fedora/23-cloud-base && vagrant up

Alternatively, to get started with Fedora Atomic host, run this command:

# vagrant init fedora/23-atomic-host && vagrant up

The above commands will grab the latest indexed images in Atlas and start a virtual machine without the user having to go download the image first. This will make it easier for Fedora users to develop and test on Fedora! If you haven't delved into Vagrant yet then you can get started by visiting the Vagrant page on the Fedora Developer Portal. Let us know on the Fedora Cloud mailing list if you have any trouble.

Dusty

Fedora 23: In the Ocean Again

Cross posted with this fedora magazine post

This week was the release week for Fedora 23, and the Fedora Project has again worked together with the DigitalOcean team to make Fedora 23 available in their service. If you're not familiar with DigitalOcean already, it is a dead simple cloud hosting platform which is great for developers.

Using Fedora on DigitalOcean

There are a couple of things to note if you are planning on using Fedora on DigitalOcean services and machines.

  • Like with other DigitalOcean images, you will log in with your ssh key as root, rather than the typical fedora user that you may be familiar with when logging in to a Fedora cloud image.
  • Similar to Fedora 21 and Fedora 22, Fedora 23 also has SELinux enabled by default.
  • In DigitalOcean images there is no firewall on by default, and there is no cloud provided firewall solution. It is highly recommended that you secure your system after you log in.
  • Fedora 23 should be available in all the newest datacenters in each region, but some legacy datacenters aren't supported.
  • If you have a problem you think is Fedora specific then drop us an email at , ping us in #fedora-cloud on freenode, or visit the Fedora cloud trac to see if it is already being worked on.

Visit the DigitalOcean Fedora landing page and spin one up today!

Happy Developing!
Dusty

Getting Ansible Working on Fedora 23

Cross posted with this fedora magazine post

Inspired mostly from a post by Lars Kellogg-Stedman.

Intro

Ansible is a simple IT automation platform written in python that makes your applications and systems easier to deploy. It has become quite popular over the past few years but you may hit some trouble when trying to run Ansible on Fedora 23.

Fedora 23 is using python 3 as the default python version that gets installed (see changes), but Ansible still requires python 2. For that reason Ansible errors out when you try to run it because it assumes python 2 by default:

GATHERING FACTS *
failed: [f23] => {"failed": true, "parsed": false}
/bin/sh: /usr/bin/python: No such file or directory

Fortunately there are a few steps you can add to your playbooks in order to fully workaround this problem. You can either choose to apply them in a single play or in mulitple plays as shown below.

Workaround - Single All-in-One Play

In the case of a single play, which is something I use often when applying configuration to vagrant boxes, you can workaround this problem by taking the following steps:

  • Explicitly disable the gathering of facts on initialization
  • Use Ansible's raw module to install python2
  • Explicitly call the setup module to gather facts again

The gathering of facts that happens by default on ansible execution will try to use python 2. We must disable this or it will fail before executing the raw ssh commands to install python 2. Fortunately we can still use facts in our single play, though, by explicitly calling the setup module after python2 is installed.

So with these minor changes applied a simple all in one play might look like:

- hosts: f23
  remote_user: fedora
  gather_facts: false
  become_user: root
  become: yes
  tasks:
    - name: install python and deps for ansible modules
      raw: dnf install -y python2 python2-dnf libselinux-python
    - name: gather facts
      setup:
    - name: use facts
      lineinfile: dest=/etc/some-cfg-file line="myip={{ ansible_eth0.ipv4.address }}" create=true

And the output of running the play should be successful:

PLAY [f23] ****************************************************************

TASK: [install python and deps for ansible modules] ***************************
ok: [f23]

TASK: [gather facts] **********************************************************
ok: [f23]

TASK: [use facts] *************************************************************
changed: [f23]

PLAY RECAP ********************************************************************
f23                        : ok=3    changed=1    unreachable=0    failed=0

Workaround - Multiple Plays

If you use multiple plays in your playbooks then you can simply have one of them do the python 2 install in raw mode while the others can remain unchanged; you don't have to explicitly gather facts because python 2 is now installed. So for the first play you would have something like:

- hosts: f23
  remote_user: fedora
  gather_facts: false
  become_user: root
  become: yes
  tasks:
    - name: install python and deps for ansible modules
      raw: dnf install -y python2 python2-dnf libselinux-python

And, re-using the code from the sample above the second play would look like:

- hosts: f23
  remote_user: fedora
  become_user: root
  become: yes
  tasks:
    - name: use facts
      lineinfile: dest=/etc/some-cfg-file line="myip={{ ansible_eth0.ipv4.address }}" create=true

Conclusion

So using these small changes you should be back up and running until Ansible adds first class support for python 3.

Enjoy!
Dusty

kubernetes skydns setup for testing on a single node

Intro

Kubernetes is (currently) missing an integrated dns solution for service discovery. In the future it will be integrated into kubernetes (see PR11599) but for now we have to setup skydns manually.

I have seen some tutorials on how to get skydns working, but almost all of them are rather involved. However, if you just want a simple setup on a single node for testing then it is actually rather easy to get skydns set up.

Setting it up

NOTE: This tutorial assumes that you already have a machine with docker and kubernetes set up and working. This has been tested on Fedora 22 and CentOS 7. It should work on other platforms but YMMV.

So the way kubernetes/skydns work together is by having two parts:

  • kube2sky - listens on the kubernetes api for new services and adds information into etcd
  • skydns - listens for dns requests and responds based on information in etcd

The easiest way to get kube2sky and skydns up and running is to just kick off a few docker containers. We'll start with kube2sky like so:

[root@f22 ~]$ docker run -d --net=host --restart=always \
                gcr.io/google_containers/kube2sky:1.11  \
                -v=10 -logtostderr=true -domain=kubernetes.local \
                -etcd-server="http://127.0.0.1:2379"

NOTE: We are re-using the same etcd that kubernetes is using.

The next step is to start skydns to respond to dns queries:

[root@f22 ~]$ docker run -d --net=host --restart=always  \
                -e ETCD_MACHINES="http://127.0.0.1:2379" \
                -e SKYDNS_DOMAIN="kubernetes.local"      \
                -e SKYDNS_ADDR="0.0.0.0:53"              \
                -e SKYDNS_NAMESERVERS="8.8.8.8:53,8.8.4.4:53" \
                gcr.io/google_containers/skydns:2015-03-11-001

The final step is to modify your kubelet configuration to let it know where the dns for the cluster is. You can do this by adding --cluster_dns and --cluster_domain to KUBELET_ARGS in /etc/kubernetes/kubelet:

[root@f22 ~]$ grep KUBELET_ARGS /etc/kubernetes/kubelet
KUBELET_ARGS="--cluster_dns=192.168.121.174 --cluster_domain=kubernetes.local"
[root@f22 ~]$ systemctl restart kubelet.service

NOTE: I used the ip address of the machine that we are using for this single node cluster.

And finally we can see our two containers running:

[root@f22 ~]$ docker ps --format "table {{.ID}}\t{{.Status}}\t{{.Image}}"
CONTAINER ID        STATUS              IMAGE
d229442f533c        Up About a minute   gcr.io/google_containers/skydns:2015-03-11-001
76d51770b240        Up About a minute   gcr.io/google_containers/kube2sky:1.11

Testing it out

Now lets see if it works! Taking a page out of the kubernetes github we'll start a busybox container and then do an nslookup on the "kubernetes service":

[root@f22 ~]$ cat > /tmp/busybox.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always
EOF
[root@f22 ~]$ kubectl create -f /tmp/busybox.yaml
pod "busybox" created
[root@f22 ~]$ kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
busybox   1/1       Running   0          16s
[root@f22 ~]$ kubectl exec busybox -- nslookup kubernetes
Server:    192.168.121.174
Address 1: 192.168.121.174

Name:      kubernetes
Address 1: 10.254.0.1

NOTE: The "kubernetes service" is the one that is shown from the kubectl get services kubernetes command.

Now you have a single node k8s setup with dns. In the future PR11599 should satisfy this need but for now this works. Enjoy!

Dusty

F23 Cloud Base Test Day September 8th!

cross posted from this fedora magazine post

Hey everyone! Fedora 23 has been baking in the oven. The Fedora Cloud WG has elected to do a temperature check on September 8th.

For this test day we are going to concentrate on the base image. We will have vagrant boxes (see this page for how to set up your machine), qcow images, raw images, and AWS EC2 images. In a later test day we will focus on the Atomic images and Docker images.

The landing page for the Fedora Cloud Base test day is here. If you're available to test on the test day (or any other time) please go there and fill out your name and test results. Also, don't forget that you can use some of our new projects testcloud (copr link) and/or Tunir to aid in testing.

Happy testing and we hope to see you on test day!

Dusty

Installing/Starting Systemd Services Using Cloud-Init

Intro

Using cloudiinit to bootstrap cloud instances and install custom sofware/services is common practice today. One thing you often want to do is install the software, enable it to start on boot, and then start it so that you don't have to reboot in order to go ahead and start using it.

The Problem

Actually starting a service can be tricky though because when executing cloud-init configuration/scripts you are essentially already within a systemd unit while you try to start another systemd unit.

To illustrate this I decided to start a Fedora 22 cloud instance and install/start docker as part of bringup. The instance I started had the following user-data:

#cloud-config
packages:
  - docker
runcmd:
  - [ systemctl, daemon-reload ]
  - [ systemctl, enable, docker.service ]
  - [ systemctl, start, docker.service ]

After the system came up and some time had passed (takes a minute for the package to get installed) here is what we are left with:

[root@f22 ~]# pstree -asp 925
systemd,1 --switched-root --system --deserialize 21
  `-cloud-init,895 /usr/bin/cloud-init modules --mode=final
      `-runcmd,898 /var/lib/cloud/instance/scripts/runcmd
          `-systemctl,925 start docker.service
[root@f22 ~]# systemctl status | head -n 5
● f22
    State: starting
     Jobs: 5 queued
   Failed: 0 units
    Since: Tue 2015-08-04 00:49:13 UTC; 30min ago

Basically the systemctl start docker.service command has been started but is blocking until it finishes. It doesn't ever finish though. As can be seen from the output above it's been 30 minutes and the system is still starting with 5 jobs queued.

I suspect this is because the start command queues the start of the docker service which then waits to be scheduled. It doesn't ever get scheduled, though, because the cloud-final.service unit needs to complete first.

The Solution

Is there a way to get the desired behavior? There is an option to systemctl that will cause it to not block during an operation, but rather just queue the action and exit. This is the --no-block option. From the systemctl man page:

--no-block
    Do not synchronously wait for the requested operation
    to finish. If this is not specified, the job will be
    verified, enqueued and systemctl will wait until it is
    completed. By passing this argument, it is only
    verified and enqueued.

To test this out I just added --no-block to the user-data file that was used previously:

#cloud-config
packages:
  - docker
runcmd:
  - [ systemctl, daemon-reload ]
  - [ systemctl, enable, docker.service ]
  - [ systemctl, start, --no-block, docker.service ]

And.. After booting the instance we get a running service:

[root@f22 ~]# systemctl is-active docker
active

Cheers!

Dusty