Build a basic Kubernetes lab

Lab to build one Master and two slave nodes.

Use kubeadm tool to bootstrap the environment. (

  1. Build three Linux (ubutnu 14.04.4 LTS) virtual machine as kubernetes hosts.
    1. Install the OS
      1. Select OpenSSH server as an option.
    2. Assign static IP Addresses( ex. kube-master; kube-node1,2,3,12,13).  The snippet below is an example config file for the regular Ubuntu 16.04 distribution.  If you’re using Ubuntu on Azure, configure a static IP through the portal or CLI.
      nano /etc/network/interfaces
      # The primary network interface
      auto ens32
      #iface ens32 inet dhcp
      iface ens32 inet static
    3. swapoff -a
    4. REM out swap file in /etc/fstab (swap is disabled by default on Azure 16.04 Ubuntu image.)
  1. Install Docker on all three: (

    1. Current (7/2018) Kubernetes release requires 17.03.x
    2. Update repository cache:
      apt-get update
    3. Install package for https and certificates:
      apt-get install -y apt-transport-https software-properties-common ca-certificates curl
    4. Add GPG key for Docker repository:
      apt-key add gpg
    5. Add the Docker repository:
      ### Ubuntu 16.04 ###
      echo "deb [arch=amd64] xenial stable" | sudo tee /etc/apt/sources.list.d/docker.list
      ### Ubuntu 17.10 ### 
      echo "deb [arch=amd64] artful stable" | sudo tee /etc/apt/sources.list.d/docker.list
      #### Ubuntu 14.04 ###
      echo "deb [arch=amd64] trusty stable" | sudo tee /etc/apt/sources.list.d/docker.list
    6. Update apt database:
      apt-get update
    7. If installing from the official Docker repository, you’ll see the desired version.  Ubuntu default repository may not have the desired version.  Run the following to see the list:
      apt-cache policy docker-ce
    8. Look for the latest 17.03 release:
      17.03.2~ce-0~ubuntu-xenial 500
        500 xenial/stable amd64 Packages
    9. Specifically install Docker 17.03.2:
      apt-get -y install docker-ce=17.03.2~ce-0~ubuntu-xenial
    10. Verify that 17.03.2-ce is installed:
      docker version
  2. Install kubeadm on all three (kubeadm, kubelet, kubectl)
    1. Install the apt-transport-https package:
      apt-get update && apt-get install -y apt-transport-https curl
    2.  Add Google GPG key:
      curl -s | apt-key add -
    3.  Add the sources list into sources.list and update repository:
      cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
      deb kubernetes-xenial main
      apt-get update
    4.  Install kubeadm and related tools:
      apt-get install -y kubelet kubeadm kubectl
  3. Initialize the master server.  On the kube-master node:
    kubeadm init --pod-network-cidr= --apiserver-advertise-address=
    1. As a regular user, run the following commands:
      mkdir -p $HOME/.kube
      sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
      sudo chown $(id -u):$(id -g) $HOME/.kube/config
    2. Collect the kubeadm join command to set things up on the other nodes.  The tokens expire after 24 hours.  If later, you’d like to add another node, one would need to generate another token.  Do this on the master:
      kubeadm token create

      A new token will be created.  Take the same command that was generated to join and substitute the old token for the new one.

  4. Set up a POD Network (cluster network) for communications between cluster nodes.  On the master node:
    kubectl apply -f
    1. Check if CoreDNS pod is running to verify pod network is installed:
      kubectl get pods --all-namespaces
    2. ensure that kube-dns-* is running before joining worker nodes.
  5. Join worker nodes to the master node
  6. Run the kubeadm join command previously collected on all the worker nodes.

Credentials Management in PowerShell

This blog is plagiarized from the best article I’ve ever found on this subject.  Full credit to Kris Powell for this amazing article found here.

Here are my condensed notes for my use.  If you find it useful, give a shout out to Kris Powell.

We now know how to convert a SecureString to an encrypted standard string. We can take any method we like to get a SecureString, convert it to a standard string and then save it to a file. Here is an example of each:

Exporting SecureString from Plain text

"P@ssword1" | `
ConvertTo-SecureString -AsPlainText -Force | `
ConvertFrom-SecureString | `
Out-File "C:\Temp 2\Password.txt"

Exporting SecureString from Get-Credential

(Get-Credential).Password | `
ConvertFrom-SecureString | `
Out-File "C:\Temp 2\Password.txt"

Exporting SecureString from Read-Host

Read-Host "Enter Password" -AsSecureString |  `
ConvertFrom-SecureString | `
Out-File "C:\Temp 2\Password.txt"

Anyone of these examples should provide you with a Password.txt file that has an encrypted standard string the represents the password.

When you need to use this encrypted password, you simply reverse the process by importing the data from your file and use ConvertTo-SecureString. If all you need is a SecureString, you can stop there. You could even take it a step further and create a PSCredential object.

Creating SecureString object

$pass = Get-Content "C:\Temp 2\Password.txt" | ConvertTo-SecureString

Creating PSCredential object

$User = "MyUserName"
$File = "C:\Temp 2\Password.txt"
$MyCredential=New-Object `
-TypeName System.Management.Automation.PSCredential `
-ArgumentList $User,
(Get-Content $File | ConvertTo-SecureString)

Get a certificate with Subject Alternative Names using certreq

If one needs to use certreq to obtain a certificate, but the certificate signing request does not explicitly ask for it, here’s the command to get it anyway:

certreq -f -q -submit -attrib “CertificateTemplate:WebServer\nSAN:dns=<hostname>&dns=<hostname><IP Address>” -config “<Config Name>” <Certificate Request File>.csr <Certificate File>.cer

The key part is in the attrib string following the new line “\n” bit where SAN: is then defined.  In this example, three are defined: the hostname, fully qualified domain name and the IP address.

Active Directory Integrated DNS Wildcard Search

So NSLOOKUP is the typical way one may query DNS.  Ever wanted to just grab the results as objects while using a wildcard filtered search?  If your DNS is Active Directory integrated, then it’s really pretty simple.  After all, each DNS entry is essentially an AD Object.  Why not query AD like we do for so many other things?  Basically, you just need the Distinguished name for the DNS zone and tell Get-ChildItem to look at Active Directory.  For example, if you wanted to find all host records ending in “-DC” in

Get-ChildItem ",CN=MicrosoftDNS,CN=System,DC=example,DC=com" -Filter "name=*-dc"

By the way, if you get an error stating something similar to this:

Cannot find drive. A drive with the name 'ad' does not exist.

Then you may need to import the Active Directory module.

Import-Module ActiveDirectory

A quick test is to do a change directory to AD.

cd ad:

and the prompt should read “PS AD:\>”

Powershell timestamp for Excel

I needed Powershell to plug in a single value to a .csv file that Excel would naturally convert to a Date and Time.  Here’s the bit to create that value:

# Native Powershell date and time

$excelDate = ((Get-Date).AddDays(1) - (Get-Date "12/31/1899")).Days
$excelTime = ((Get-Date -Format HH)/24)+((Get-Date -Format mm)/1440)+((Get-Date -Format ss)/86400)
$excelTimeStamp = $excelDate + $excelTime


Disable TLS on Windows 2012 R2 (IIS 8)

A handy GUI tool to make this an easy one-off thing is IIS Crypto.

Here’s the actual registry change that is made if you need to script it:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0]

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client]

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server]

A reboot is required for the change to apply.

Multiple KMS keys confusion

If you have access to a VLSC and can get KMS licenses, you may see keys for different Operating systems.  Intuitively, that suggests you would register each key to be able to activate a corresponding operating system.  Not so.  Get the highest level operating system KMS and subsequent operating systems are covered by the one key.  For example, Windows 2016 covers 2012, 2008, 10, and so on…

Check out this article for more detail: Windows Server 2016 Activation

Office 2016 KMS license in Windows 2012 is a bit goofy.  Intuitively, you’d think you would use the Volume Activation Tools to plug in your key.  Nope.

Download and run the Microsoft Office 2016 Volume License Pack.  It will launch the VAT GUI and then you can plug in your KMS license.

Why is it done that way?  I honestly don’t know.  I’m sure there’s a Microsoft explanation why but I don’t feel like digging through the Internet to find an obscure article with an unofficial explanation.  I’m just glad I finally got the KMS license thing set up.

Career and Professional Website