Skip to content

Instantly share code, notes, and snippets.

@ct27stf
Last active June 23, 2022 16:05
Show Gist options
  • Save ct27stf/77582676a42e2f409ccd227773393623 to your computer and use it in GitHub Desktop.
Save ct27stf/77582676a42e2f409ccd227773393623 to your computer and use it in GitHub Desktop.
MicroK8s install scripts for our dev team

Install script for MicroK8s for our dev team

  • This will setup MicroK8s either on Windows with WSL2 or Ubuntu
  • Requires Ubuntu >= 20.04

Windows

This will configure WSL2. Keep in mind that if you previously installed WSL, all your distros WILL be removed by this script

It will download the SetupWSL.ps1 install script

  • Open a PowerShell instance with Administrator privileges

  • Paste the following command

    Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://gist.github.com/ct27stf/77582676a42e2f409ccd227773393623/raw/SetupWSL.ps1'))
  • If Windows requires a reboot, please do it and rerun this script

  • You will be presented with Windows Store, install and lauch Ubuntu

  • After you create your user and password, continue with the Linux section.

Linux

Ubuntu >= 20.04 is required.

This will run the SetupMicroK8s.sh script, which is a convenience method that will doanload and run the ansible-microk8s.yml playbook file into your $HOME dir, install ansible if not found and run the playbook

  • Open a terminal and paste the folowing

    curl -sf -L https://gist.github.com/ct27stf/77582676a42e2f409ccd227773393623/raw/SetupMicroK8s.sh | sh
  • It will update your system, install minimum required dev tools and microk8s

  • It will work on both WSL2 and standalone Ubuntu installs

  • If you are on a WSL install:

    1. The script will terminate the process in order to simulate a reboot and setup SystemD
    2. Relaunch your Ubuntu instance and run
      ansible-playbook -K ~/ansible-microk8s.yml
    3. After the script finishes, you will need to logout by pressing Ctrl-D and reopen your instance

SSH keys and WSL

Due to inconsistencies between the filesystems, ssh keys can't be easily shared

If you already use ssh keys in Windows

Such as keys created by Github Desktop or Sourcetree

  1. You can copy your ssh keys into WSL.
    # From your WSL instance
    mkdir ~/.ssh
    # Copy the keys from Windows. Replace %USERNAME% with your own Windows username
    cp -r /mnt/c/Users/%USERNAME%/.ssh/* ~/.ssh/
    # Fix permissions
    chmod 600 ~/.ssh/*
  2. Now add all private keys to keychain
    keychain --nogui $HOME/.ssh/id_*
  3. Make keychain remember agent sessions
    echo -en "keychain --nogui $HOME/.ssh/id_*[^.pub]\nsource $HOME/.keychain/$HOSTNAME-sh" >> ~/.bashrc
  4. Logout with CTRL-D and start a new session

If you don't have any keys

  1. You will need to generate a new ssh key
    ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/id_ed25519 -C "${LOGNAME}@${HOSTNAME}"
  2. Add the key
    keychain --nogui $HOME/.ssh/id_ed25519
  3. Make keychain remember agent sessions
    echo -en "keychain --nogui $HOME/.ssh/id_*[^.pub]\nsource $HOME/.keychain/$HOSTNAME-sh" >> ~/.bashrc
  4. Logout with CTRL-D and start a new session

Credits

This was build on top of the works of

---
- hosts: localhost
tasks:
- name: Update Ubuntu system
become: yes
apt:
name: "*"
state: latest
update_cache: yes
when:
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: WSL needed packages for SystemD
become: yes
apt:
name: '{{ packages }}'
vars:
packages:
- daemonize
- dbus-user-session
- fontconfig
when:
- ansible_facts['env']['WSLENV'] is defined
- ansible_facts['env']['WSL_DISTRO_NAME'] is defined
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Fix SystemD if we are on WSL Part I
become: yes
copy:
dest: "/usr/sbin/start-systemd-namespace"
owner: root
group: root
mode: 644
force: no
content: |
#!/bin/bash
SYSTEMD_EXE="/lib/systemd/systemd --unit=basic.target"
SYSTEMD_PID="$(ps -eo pid=,args= | awk '$2" "$3=="'"$SYSTEMD_EXE"'" {print $1}')"
if [ "$LOGNAME" != "root" ] && ( [ -z "$SYSTEMD_PID" ] || [ "$SYSTEMD_PID" != "1" ] ); then
export | sed -e 's/^declare -x //;/^IFS=".*[^"]$/{N;s/\n//}' | \
grep -E -v "^(BASH|BASH_ENV|DIRSTACK|EUID|GROUPS|HOME|HOSTNAME|\
IFS|LANG|LOGNAME|MACHTYPE|MAIL|NAME|OLDPWD|OPTERR|\
OSTYPE|PATH|PIPESTATUS|POSIXLY_CORRECT|PPID|PS1|PS4|\
SHELL|SHELLOPTS|SHLVL|SYSTEMD_PID|UID|USER|_)(=|\$)" > "$HOME/.systemd-env"
export PRE_NAMESPACE_PATH="$PATH"
export PRE_NAMESPACE_PWD="$(pwd)"
exec sudo /usr/sbin/enter-systemd-namespace "$BASH_EXECUTION_STRING"
fi
if [ -n "$PRE_NAMESPACE_PATH" ]; then
export PATH="$PRE_NAMESPACE_PATH"
unset PRE_NAMESPACE_PATH
fi
if [ -n "$PRE_NAMESPACE_PWD" ]; then
cd "$PRE_NAMESPACE_PWD"
unset PRE_NAMESPACE_PWD
fi
register: wsl_systemd_fix1
when:
- ansible_facts['env']['WSLENV'] is defined
- ansible_facts['env']['WSL_DISTRO_NAME'] is defined
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Fix SystemD if we are on WSL Part II
become: yes
copy:
dest: "/usr/sbin/enter-systemd-namespace"
owner: root
group: root
mode: 754
force: no
content: |
#!/bin/bash --norc
if [ "$LOGNAME" != "root" ]; then
echo "You need to run $0 through sudo"
exit 1
fi
if [ -x /usr/sbin/daemonize ]; then
DAEMONIZE=/usr/sbin/daemonize
elif [ -x /usr/bin/daemonize ]; then
DAEMONIZE=/usr/bin/daemonize
else
echo "Cannot execute daemonize to start systemd."
exit 1
fi
if ! command -v /lib/systemd/systemd > /dev/null; then
echo "Cannot execute /lib/systemd/systemd."
exit 1
fi
if ! command -v /usr/bin/unshare > /dev/null; then
echo "Cannot execute /usr/bin/unshare."
exit 1
fi
SYSTEMD_EXE="/lib/systemd/systemd --unit=basic.target"
SYSTEMD_PID="$(ps -eo pid=,args= | awk '$2" "$3=="'"$SYSTEMD_EXE"'" {print $1}')"
if [ -z "$SYSTEMD_PID" ]; then
"$DAEMONIZE" /usr/bin/unshare --fork --pid --mount-proc bash -c 'export container=wsl; mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc; exec '"$SYSTEMD_EXE"
while [ -z "$SYSTEMD_PID" ]; do
echo "Sleeping for 1 second to let systemd settle"
sleep 1
SYSTEMD_PID="$(ps -eo pid=,args= | awk '$2" "$3=="'"$SYSTEMD_EXE"'" {print $1}')"
done
fi
USER_HOME="$(getent passwd | awk -F: '$1=="'"$SUDO_USER"'" {print $6}')"
if [ -n "$SYSTEMD_PID" ] && [ "$SYSTEMD_PID" != "1" ]; then
if [ -n "$1" ] && [ "$1" != "bash --login" ] && [ "$1" != "/bin/bash --login" ]; then
exec /usr/bin/nsenter -t "$SYSTEMD_PID" -a \
/usr/bin/sudo -H -u "$SUDO_USER" \
/bin/bash -c 'set -a; [ -f "$HOME/.systemd-env" ] && source "$HOME/.systemd-env"; set +a; exec bash -c '"$(printf "%q" "$@")"
else
exec /usr/bin/nsenter -t "$SYSTEMD_PID" -a /bin/login -p -f "$SUDO_USER"
fi
echo "Existential crisis"
exit 1
fi
register: wsl_systemd_fix2
when:
- ansible_facts['env']['WSLENV'] is defined
- ansible_facts['env']['WSL_DISTRO_NAME'] is defined
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Fix SystemD if we are on WSL Part III
become: yes
copy:
dest: "/etc/sudoers.d/00-wsl-systemd"
owner: root
group: root
mode: 440
force: no
content: |
Defaults env_keep += WSLPATH
Defaults env_keep += WSLENV
Defaults env_keep += WSL_INTEROP
Defaults env_keep += WSL_DISTRO_NAME
Defaults env_keep += PRE_NAMESPACE_PATH
Defaults env_keep += PRE_NAMESPACE_PWD
%sudo ALL=(ALL) NOPASSWD: /usr/sbin/enter-systemd-namespace
validate: visudo -cf %s
register: wsl_systemd_fix3
when:
- ansible_facts['env']['WSLENV'] is defined
- ansible_facts['env']['WSL_DISTRO_NAME'] is defined
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Fix SystemD if we are on WSL Part IV
become: yes
blockinfile:
path: "/etc/bash.bashrc"
marker: "# {mark} WSL2 SystemD workaround"
insertafter: EOF
block: |
# Start or enter a PID namespace in WSL2
source /usr/sbin/start-systemd-namespace
register: wsl_systemd_fix4
when:
- ansible_facts['env']['WSLENV'] is defined
- ansible_facts['env']['WSL_DISTRO_NAME'] is defined
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- pause:
prompt: |
We need to terminate the session for the WSL fix!
Please reopen your WSL and rerun this script with
ansible-playbook -K ~/ansible-microk8s.yml
Press ENTER to continue...
when:
- ansible_facts['env']['WSLENV'] is defined
- ansible_facts['env']['WSL_DISTRO_NAME'] is defined
- (wsl_systemd_fix1 is changed) or
(wsl_systemd_fix2 is changed) or
(wsl_systemd_fix3 is changed) or
(wsl_systemd_fix4 is changed)
- name: We need to reboot WSL
shell: "wsl.exe -t {{ ansible_facts['env']['WSL_DISTRO_NAME'] }}"
when:
- ansible_facts['env']['WSLENV'] is defined
- ansible_facts['env']['WSL_DISTRO_NAME'] is defined
- (wsl_systemd_fix1 is changed) or
(wsl_systemd_fix2 is changed) or
(wsl_systemd_fix3 is changed) or
(wsl_systemd_fix4 is changed)
- name: Install playbook deps
become: yes
apt:
name: '{{ packages }}'
vars:
packages:
- python3-apt
when:
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Install 3rd party repo keys
become: yes
apt_key:
url: '{{ item }}'
state: present
with_items:
- https://deb.nodesource.com/gpgkey/nodesource.gpg.key
- https://apt.releases.hashicorp.com/gpg
when:
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Install 3rd party repos
become: yes
apt_repository:
repo: '{{ item.repo }}'
filename: '{{ item.filename }}'
update_cache: yes
loop:
- { repo: 'deb https://deb.nodesource.com/node_14.x focal main', filename: 'nodesource' }
- { repo: 'ppa:git-core/ppa', filename: ''}
- { repo: 'deb [arch=amd64] https://apt.releases.hashicorp.com focal main', filename: 'hashicorp'}
when:
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Install utils
become: yes
apt:
name: '{{ packages }}'
vars:
packages:
- git
- git-extras
- git-lfs
- git-quick-stats
- git-secrets
- git-sizer
- git-svn
- gitbatch
- mc
- pigz
- xz-utils
when:
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Install utils for WSL
become: yes
apt:
name: '{{ packages }}'
vars:
packages:
- keychain
when:
- ansible_facts['env']['WSLENV'] is defined
- ansible_facts['env']['WSL_DISTRO_NAME'] is defined
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Restart snapd.seeded.service
become: yes
systemd:
name: snapd.seeded.service
state: reloaded
enabled: yes
when:
- ansible_facts['env']['WSLENV'] is defined
- ansible_facts['env']['WSL_DISTRO_NAME'] is defined
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Install MicroK8s
become: yes
snap:
name: microk8s
channel: "1.19/stable"
classic: yes
when:
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Add current user "{{ ansible_user }}" to group microk8s
become: yes
user:
name: "{{ ansible_user }}"
groups: microk8s
append: yes
- name: Enable Mikrok8s Helm3 and Kubectl
shell: sudo -iu {{ansible_user_id}} microk8s enable kubectl helm3
when:
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Add bash completion for microk8s.kubectl
shell: sudo -iu {{ansible_user_id}} echo "source <(microk8s.kubectl completion bash)" >> ~/.bashrc
when:
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
- name: Add bash completion for microk8s.helm3
shell: sudo -iu {{ansible_user_id}} echo "source <(microk8s.helm3 completion bash)" >> ~/.bashrc
when:
- ansible_facts['distribution'] == "Ubuntu" and ansible_facts['distribution_major_version'] >= '20'
#!/usr/bin/env bash
if ! [ -x "$(command -v ansible)" ]; then
echo 'Ansible not found. Installing'
sudo apt update && sudo apt install -y -qq ansible </dev/null
fi
echo 'Downloading ansible-microk8s playbook'
curl -sf -L -o $HOME/ansible-microk8s.yml https://gist.github.com/ct27stf/77582676a42e2f409ccd227773393623/raw/ansible-microk8s.yml
chown $(id -u):$(id -g) $HOME/ansible-microk8s.yml
echo 'Running playbook'
ansible-playbook -l localhost -K $HOME/ansible-microk8s.yml
function Test-Administrator {
[OutputType([bool])]
param()
process {
[Security.Principal.WindowsPrincipal]$user = [Security.Principal.WindowsIdentity]::GetCurrent();
return $user.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator);
}
}
function Test-WindowsVersion
{
[OutputType([bool])]
param()
process {
if ([System.Environment]::OSVersion.Platform -eq "Win32NT") {
if ([System.Environment]::Is64BitOperatingSystem) {
if ([System.Environment]::OSVersion.Version.Major -ge 10) {
if ([System.Environment]::OSVersion.Version.Build -ge 18362) {
return $true;
}
}
}
}
return $false;
}
}
function Enable-WSLFeature
{
Write-Host "Enabling Microsoft-Windows-Subsystem-Linux";
$WSL = Get-WindowsOptionalFeature -Online -FeatureName "Microsoft-Windows-Subsystem-Linux" | Select-Object -ExpandProperty State;
if ($WSL -ne "Enabled") {
try {
Enable-WindowsOptionalFeature -Online -FeatureName "Microsoft-Windows-Subsystem-Linux" -All -NoRestart;
}
catch {
Write-Host "Error enabling WSL";
Write-Host $_;
exit 1;
}
}
}
function Enable-VirtualizationFeature
{
Write-Host "Enabling VirtualMachinePlatform";
$FirmwareVirt = Get-CimInstance Win32_Processor | Select-Object -ExpandProperty VirtualizationFirmwareEnabled;
$VMP = Get-WindowsOptionalFeature -Online -FeatureName "VirtualMachinePlatform" | Select-Object -ExpandProperty State;
if ($FirmwareVirt -ne "True") {
throw "Your system does not have Virtualization support, or it is not enabled in the BIOS";
}
if ($VMP -ne "Enabled") {
try {
Enable-WindowsOptionalFeature -Online -FeatureName "VirtualMachinePlatform" -All;
}
catch {
Write-Host "Error enabling VirtualMachinePlatform";
Write-Host $_;
exit 1;
}
}
}
function Install-WSLKernelUpdate {
param ()
process {
Write-Host "Downloading and installing the latest WSL Kernel update";
$link = "https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi";
$client = New-Object System.Net.WebClient;
try {
$client.DownloadFile($link, "$env:TEMP\wsl_update_x64.msi")
}
catch {
Write-Host "Error downloading WSL kernel update from $link";
Write-Host $_;
exit 1;
}
try {
msiexec /i "$env:TEMP\wsl_update_x64.msi" /qn
}
catch {
Write-Host "Error installing WSL kernel update from $env:TEMP\wsl_update_x64.msi";
Write-Host $_;
exit 1;
}
wsl --set-default-version 2
}
}
function Update-InstalledDistros
{
param()
process {
Write-Host "Cleaning WSL"
$wsl_distros = wsl -l --all -q;
$wsl_distros = $wsl_distros | ? { $_ -ne "" }
foreach ($distro in $wsl_distros) {
Start-Process -FilePath "wsl" -NoNewWindow -ArgumentList "--unregister $distro" -Wait
}
Start-Process ms-windows-store://pdp/?ProductId=9N6SVWS3RX71
}
}
if (-not (Test-Administrator)) {
Write-Host "This script must be executed as Administrator.";
exit 1;
}
if (-not (Test-WindowsVersion)) {
Write-Host "This script Windows 10 buid 18362 or higher";
Write-Host "Your version is:";
Write-Host [System.Environment]::OSVersion;
exit 1;
}
Enable-WSLFeature;
Enable-VirtualizationFeature;
Install-WSLKernelUpdate;
Update-InstalledDistros;
exit 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment