What is Kubernetes really?

As I take the deep dive into kubernetes what I’m finding is, though definitely a container management system, it can also been seen as a controller yaml processing engine.  Let me explain.

Kubernetes understands what a deployment is, and what a service is, these are defined as yaml and loaded.  Deployments and services can be seen as controllers which understand those types of objects defined in yaml.

What is interesting about this is that we can implement our own controllers.  For example, I could implement a controller that understands how to manage a tic-tac-toe game.  That controller could also implement an ai that knows how to play the game.  In the same way you can edit a deployment you could edit the game and the kubernetes infrastructure could respond to the change.  Or, a move could be another type recognized by the game controller, so you could create a move associated with a game in the same way you can create a service associated with a deployment.

You can imagine doing a ‘k get games’ and seeing the games being played listed out.  As well as ‘k describe game a123’ to get the details and status of the game.

Seems I’m not the only one who has started thinking down this line.  A quick Google search reveals agones.

This is fascinating and gives me a lot of ideas on how I might reimplement my list processing server & generic game server, within the kubernetes framework.

New helm chart: wireguard-centos-8-stream


My first helm chart, a fun milestone.  Used it to install my new docker container uploaded to quay.io this morning.

Nice feeling to give back to the open source community.

Now to automate:
* watch for wireguard updates & release an updated docker image
* watch for a centos-8-stream update & release an updated docker image
* watch for a helm chart update & update what is necessary for those changes to be seen

But first, time to investigate and implement longhorn.


New container: docker-wireguard-centos-8-stream

A wireguard container built for centos-8-stream which takes advantage of the scripts from the linuxserver docker-wireguard project.

Source: https://github.com/lknight-gh/docker-wireguard-centos-8-stream

LinuxServer docker-wireguard project: https://github.com/linuxserver/docker-wireguard

To use simply replace the docker-wireguard image with: quay.io/lknight/docker-wireguard-centos-8-stream:latest

Note: Initial startup may take quite awhile, 4 minutes +, if the wireguard module is being recompiled. Be sure to use a volume for the modules folder to avoid having to recompile.

Multiple Hyper-V virtual switch lab environments requires PowerShell

Windows Server 2019

The Internet Connection Sharing tab can be found by viewing the Ethernet Properties of a network connection.  This can be used to select a Hyper-V virtual switch in order to enable a Hyper-V virtual switch of the “Internal” network style Internet access via the Hyper-V server.

But what if you’d like to have more than one lab network setup in this way?  PowerShell to the rescue:

New-VMSwitch -SwitchName "lab10" -SwitchType Internal
New-NetIPAddress -IPAddress -PrefixLength 24 -InterfaceAlias "vEthernet (lab10)"
New-NetNAT -Name "lab10" -InternalIPInterfaceAddressPrefix

New-VMSwitch -SwitchName "lab20" -SwitchType Internal
New-NetIPAddress -IPAddress -PrefixLength 24 -InterfaceAlias "vEthernet (lab20)"
New-NetNAT -Name "lab20" -InternalIPInterfaceAddressPrefix

New-VMSwitch -SwitchName "lab30" -SwitchType Internal
New-NetIPAddress -IPAddress -PrefixLength 24 -InterfaceAlias "vEthernet (lab30)"
New-NetNAT -Name "lab30" -InternalIPInterfaceAddressPrefix

New-VMSwitch -SwitchName "lab40" -SwitchType Internal
New-NetIPAddress -IPAddress -PrefixLength 24 -InterfaceAlias "vEthernet (lab40)"
New-NetNAT -Name "lab40" -InternalIPInterfaceAddressPrefix

Infrastructure as code and an infinite trial period

If you implement infrastructure as code with something such as ansible, you will be able to spin up a new VM and automatically setup the software.

An interesting side effect of this is you can wipe and reload a system, running say System Center, over night just before the trial period ends.  Perhaps this a gray area, getting around the intention of a trial period, but an interesting side effect none the less.

Using infrastructure as code requires that you back up everything, in order to restore things if desired.  This means the home pc can also be reloaded at will, if network drives are used or some other backup method is used, leading to the fastest performance possible when otherwise a PC has the tendency to slow down over time.

DevOps, what a beautiful thing.

Note: The current subscription fee to have access to all Microsoft software for a development/lab environment is $45 a month Visual Studio Professional Monthly Subscription.

image files, wim files, mdt, pxe, and kms

In an isolated test environment it can be interesting to experiment with available technologies, though some might be questionable (hence the isolated test environment).

Steps to perform:

  1. Rip available .wim files from an OS install dvd
  2. Setup and configure MDT (and optionally WDS server)
  3. Install py-kms as an experiment
  4. Import .wim file into MDT
  5. Target py-kms as part of your task sequence or configure as DNS SRV record
  1. Rip available .wim files from an OS install dvd
Convert install images from a source DVD to individual .wim files, ready for MDT

DVDs come ready with multiple images to install in various formats, before importing
into MDT for the purpose of PXE booting it is necessary to obtain individual .wim

Author: Travis Loyd
  Date: 2020-11-08
Param (
    # Path to DVD including sources folder
    [Parameter(Mandatory=$true, Position=0)]
    [string]$SourceImagePath = "D:\sources",

    # Target folder where ripped .wim images are stored
    [Parameter(Mandatory=$true, Position=1)]
    [string]$DestinationImagePath = "E:\ISO_Import"

# Various install file format styles
$SupportedExtensions = @("esd","swm","wim")
foreach ($Extension in $SupportedExtensions) {
    # Next potential source file
    $SourceImageFile = "$($SourceImagePath)\install.$($Extension)"

    # Skip if not found
    if (-not (Test-Path $SourceImageFile)) {

    # debug
    Write-Host "Working with '$SourceImageFile'"

    # Loop through images contained within install file
    $Images = Get-WindowsImage -ImagePath $SourceImageFile
    foreach ($Image in $Images) {
        # debug
        Write-Host "$($Image.ImageIndex): $($Image.ImageName)"

        # Form resultant wim file name
        $DestinationName = "$(($Image.ImageName -split " ") -join "_").wim"
        $DestinationImagefile = "$DestinationImagePath\$DestinationName"

        # Handle possible extension types
        switch ($Extension) {
            "esd" {
                dism /export-image /SourceImageFile:$($SourceImageFile) /SourceIndex:$($Image.ImageIndex) /DestinationImageFile:$($DestinationImagefile) /Compress:max /CheckIntegrity
            "swm" {        
                # prep
                $SwmFile = "$($SourceImagePath)\install*.swm"

                dism /export-image /SourceImageFile:$($SourceImageFile) /swmfile:$($SwmFile) /SourceIndex:$($Image.ImageIndex) /DestinationImageFile:$($DestinationImagefile) /Compress:max /CheckIntegrity
            "wim" {
                dism /export-image /SourceImageFile:$($SourceImageFile) /SourceIndex:$($Image.ImageIndex) /DestinationImageFile:$($DestinationImagefile) /Compress:max /CheckIntegrity

2. Left up to the reader as an exercise

3. Install and configure docker then:

docker run -d --name py-kms --restart always -p 1688:1688 pykmsorg/py-kms

4. Left up to the reader as an exercise

5. Left up to the reader as an exercise

Multisite WordPress installation using a Docker image

If you’ve ever thought about setting up a multisite WordPress installation via Docker I highly recommend you do so as it is an excellent project to revisit several topics.


  1. Load new Oracle 7.7 system via PXE and join to domain
  2. Install Docker & Docker Compose
  3. Acquire Docker Compose script from online video (Reference: https://www.youtube.com/watch?v=pYhLEV-sRpY)
  4. Modify script to work in an SELinux enabled environment
  5. Modify script to work with multisite
  6. Modify script to allow a larger upload size
  7. Run Docker Compose
  8. Configure WordPress for multisite
  9. Setup DNS entries & modify sites to use full domain names

What is great about this Docker setup is by stopping and then restarting the Docker Compose, WordPress will automatically be updated if a new release has come out.  With a High Availability setup, you can restart one WordPress instance at a time, allowing for no downtime during upgrades.

Start with a clean installation. For this presentation I’m using Oracle Linux 7.7, which is based on Red Hat, similar to the way CentOS is though with its own repositories.
Configure host & setup user (or join domain). Logout & switch to user account.
My repositories were configured automatically via the PXE kickstart file. For those new to Oracle Linux instructions for setting up repositories can be found here:
(docker is provided by ol7_addons repo)
(python-pip is provided by ol7_developer_EPEL repo)
# install docker
sudo yum -y install docker

# add user who will be running docker to docker group
sudo usermod -aG docker travis

# enable docker to start up at boot & start
sudo systemctl enable docker
sudo systemctl start docker

# install pip which will be used to install docker-compose
sudo yum -y install python-pip

# install docker-compose
sudo pip install docker-compose
# create directory to store docker compose configuration & change to it
mkdir -p docker/wordpress
cd docker/wordpress

# create uploads.ini file which is used to configure a larger upload size
cat > uploads.ini
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 400M
file_uploads = On
max_execution_time = 180

# create docker-compose.yaml file
# original version: https://www.youtube.com/watch?v=pYhLEV-sRpY
cat > docker-compose.yaml
version: '3'
   # Database
     image: mysql:5.7
       - db_data:/var/lib/mysql
     restart: always
       MYSQL_ROOT_PASSWORD: password
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: password
       - wpsite
   # WordPress
       - db
     image: wordpress:latest
       - '80:80'
     restart: always
     privileged: true
       - ./html:/var/www/html
       - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: password
       - wpsite

Notes on docker-compose.yaml:
1. MySQL is loaded via Container image. Data is stored in local volume.
2. MySQL & WordPress are able to interact via a local network wpsite.
3. With a Multisite configuration port 80 is required.
4. “Privileged” must be used as we are using an enforced SELinux environment.

# create directory to store wordpress files
mkdir html

# Start up WordPress via docker-compose
docker-compose up -d

# Configure firewall
firewall-cmd --permanent --add-port 80
firewall-cmd --reload

Next a configuration file must be modified:

Locate the string “That’s all, stop editing! …” and add the following lines after:

define(‘WP_ALLOW_MULTISITE’, ‘true’);

After logging into the WordPress site for the first time browse to:
Tools -> Network, choose subdomains or subfolders and follow directions.

Finally, you can use a domain instead of a subdomain or subfolder by first creating a site with a subdomain or subfolder then, after configuring the domain in DNS, go back to the site and modifying the URL with the domain. For example: wp-1.com/travisloyd –> www.travisloyd.xyz