<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Michael Ransley</title>
    <description>The Website of Michael Ransley</description>
    <link>/</link>
    <atom:link href="/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 19 Apr 2022 22:02:36 -0500</pubDate>
    <lastBuildDate>Tue, 19 Apr 2022 22:02:36 -0500</lastBuildDate>
    <generator>Jekyll v4.2.1</generator>

    
      <item>
        <title>Install Zookeeper on Ubuntu 20.04</title>
        <description>&lt;p&gt;Apache Zookeeper is required to support a number of software packages.  In order to use my homelab I run this locally in the foreground to allow me to check each component - I know that I could just as easily do this in k8s but I like to turn components on and off as required - which I know that I could do in k8s.&lt;/p&gt;

&lt;p&gt;This procedure assumes a working install of Ubuntu 20.04 with Java installed.&lt;/p&gt;

&lt;p&gt;To install and run Zookeeper execute the following commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.0/apache-zookeeper-3.8.0-bin.tar.gz
tar xfvz apache-zookeeper-3.8.0-bin.tar.gz
ln -s apache-zookeeper-3.8.0-bin zookeeper
cd zookeeper
cp conf/zoo_sample.cfg conf/zoo.cfg
bin/zkServer.sh start-foreground
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This should then start cleanly.&lt;/p&gt;
</description>
        <pubDate>Fri, 25 Mar 2022 00:00:00 -0500</pubDate>
        <link>/blog/ubuntu_20.04_zookeeper_install/</link>
        <guid isPermaLink="true">/blog/ubuntu_20.04_zookeeper_install/</guid>
      </item>
    
      <item>
        <title>Install Kafka on Ubuntu 20.04</title>
        <description>&lt;p&gt;Apache Kafka is a streaming service that I am looking to play with in a home lab.  In order to use my homelab I run this locally in the foreground to allow me to check each component - I know that I could just as easily do this in k8s but I like to turn components on and off as required - which I know that I could do in k8s.&lt;/p&gt;

&lt;p&gt;This procedure assumes a working install of Ubuntu 20.04 with Java and &lt;a href=&quot;/blog/ubuntu_20.04_zookeeper_install/&quot;&gt;Zookeeper&lt;/a&gt; installed.&lt;/p&gt;

&lt;p&gt;To install and run Kafka execute the following commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget https://dlcdn.apache.org/kafka/3.1.0/kafka_2.13-3.1.0.tgz
tar xfvz kafka_2.13-3.1.0.tgz
ln -s kafka_2.13-3.1.0 kafka
cd kafka
bin/kafka-server-start.sh config/server.properties
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 25 Mar 2022 00:00:00 -0500</pubDate>
        <link>/blog/ubuntu_20.04_kafka_install/</link>
        <guid isPermaLink="true">/blog/ubuntu_20.04_kafka_install/</guid>
      </item>
    
      <item>
        <title>Install Druid on Ubuntu 20.04</title>
        <description>&lt;p&gt;Apache Druid is a streaming service that I am looking to play with in a home lab.  In order to use my homelab I run this locally in the foreground to allow me to check each component - I know that I could just as easily do this in k8s but I like to turn components on and off as required - which I know that I could do in k8s.&lt;/p&gt;

&lt;p&gt;This procedure assumes a working install of Ubuntu 20.04 with Java 8 and &lt;a href=&quot;/blog/ubuntu_20.04_zookeeper_install/&quot;&gt;Zookeeper&lt;/a&gt; installed.&lt;/p&gt;

&lt;p&gt;To install and run Druid execute the following commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget wget https://dlcdn.apache.org/druid/0.22.1/apache-druid-0.22.1-bin.tar.gz
tar xfvz apache-druid-0.22.1-bin.tar.gz
ln -s apache-druid-0.22.1 druid
cd druid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Edit the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config/supervise/single-server/small.conf&lt;/code&gt; and comment out the following lines:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:verify bin/verify-default-ports
#!p10 zk bin/run-zk conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Both of these assume that we are not running a shared zookeeper instance.  To start the server run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bin/start-single-server-small
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To open the druid console open a browser to &lt;a href=&quot;http://localhost:8888/&quot;&gt;http://localhost:8888/&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 25 Mar 2022 00:00:00 -0500</pubDate>
        <link>/blog/ubuntu_20.04_druid_install/</link>
        <guid isPermaLink="true">/blog/ubuntu_20.04_druid_install/</guid>
      </item>
    
      <item>
        <title>Install K3S on Ubuntu 20.04</title>
        <description>&lt;p&gt;I am mucking around a bit with a homelab and thought I would look into K3s.  To start, I created an absolutely vanilla Ubuntu 20.04 Server instance with 8Gb of Memory and 30Gb of disk.  Then I ran the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl -sfL https://get.k3s.io | sh -
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The output of the command is as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[INFO]  Finding release for channel stable
[INFO]  Using v1.22.6+k3s1 as release
[INFO]  Downloading hash https://github.com/k3s-io/k3s/releases/download/v1.22.6+k3s1/sha256sum-amd64.txt
[INFO]  Downloading binary https://github.com/k3s-io/k3s/releases/download/v1.22.6+k3s1/k3s
[INFO]  Verifying binary download
[INFO]  Installing k3s to /usr/local/bin/k3s
[INFO]  Skipping installation of SELinux RPM
[INFO]  Creating /usr/local/bin/kubectl symlink to k3s
[INFO]  Creating /usr/local/bin/crictl symlink to k3s
[INFO]  Creating /usr/local/bin/ctr symlink to k3s
[INFO]  Creating killall script /usr/local/bin/k3s-killall.sh
[INFO]  Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO]  env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO]  systemd: Creating service file /etc/systemd/system/k3s.service
[INFO]  systemd: Enabling k3s unit
Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service.
[INFO]  systemd: Starting k3s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should then be able to query the node details running:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo k3s kubectl get node
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which should output something like the following&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NAME   STATUS   ROLES                  AGE    VERSION
k3s    Ready    control-plane,master   3m4s   v1.22.6+k3s1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 28 Feb 2022 00:00:00 -0600</pubDate>
        <link>/blog/ubuntu_20.04_k3s_install/</link>
        <guid isPermaLink="true">/blog/ubuntu_20.04_k3s_install/</guid>
      </item>
    
      <item>
        <title>Install Tanzu on Ubuntu 20.04</title>
        <description>&lt;p&gt;I am mucking around a bit with a homelab and thought I would look into Tanzu.  To start, I created an absolutely vanilla Ubuntu 20.04 Server instance with 8Gb of Memory and 30Gb of disk.  In then installed some pre-requisite software:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/ubuntu_20.04_docker_install/&quot;&gt;Docker&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/ubuntu_20.04_brew_install/&quot;&gt;Brew&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/ubuntu_20.04_kubectl_install/&quot;&gt;Kubectl&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To install Tanzu run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install vmware-tanzu/tanzu/tanzu-community-edition
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command will output something similar to the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;==&amp;gt; ******************************************************************************
==&amp;gt; * To initialize all plugins required by Tanzu Community Edition, an additional
==&amp;gt; * step is required. To complete the installation, please run the following
==&amp;gt; * shell script:
==&amp;gt; *
==&amp;gt; * /home/linuxbrew/.linuxbrew/Cellar/tanzu-community-edition/v0.10.0/libexec/configure-tce.sh
==&amp;gt; *
==&amp;gt; ******************************************************************************
==&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Run that command, then run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tanzu management-cluster create --ui --bind 0.0.0.0:8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The bind address is required because my ubuntu server does not have a GUI, I am accessing it via SSH.&lt;/p&gt;

&lt;p&gt;To run the management console open up a browser and point to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://&amp;lt;tanzu_server_ip&amp;gt;:8080&lt;/code&gt; and it should display something similar to the following:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/tanzu_cluster_management.png&quot; alt=&quot;Tanzu Cluster Management&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Click on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Docker&lt;/code&gt; deploy option and this moves you through a prerequisite check, cluster naming and some network configuration, I accepted the defaults.&lt;/p&gt;

&lt;p&gt;I then reviewed the configuration and chose “Deploy Management Cluster” as shown below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/tanzu_cluster_creation.png&quot; alt=&quot;Tanzu Cluster Creation&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This then moves though a deployment process which takes some time (minutes in my case).  Logs can either be viewed in the GUI and command line and when the process completes the command executed earlier will exit.&lt;/p&gt;

&lt;p&gt;To validate that the cluster is running, run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tanzu management-cluster get
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For my server this returned the following information:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  NAME     NAMESPACE   STATUS   CONTROLPLANE  WORKERS  KUBERNETES        ROLES
ransley  tkg-system  running  1/1           1/1      v1.21.5+vmware.1  management


Details:

NAME                                                        READY  SEVERITY  REASON  SINCE  MESSAGE
/ransley                                                    True                     2m55s
├─ClusterInfrastructure - DockerCluster/ransley             True                     3m5s
├─ControlPlane - KubeadmControlPlane/ransley-control-plane  True                     2m55s
│ └─Machine/ransley-control-plane-n7sgp                     True                     2m59s
└─Workers
└─MachineDeployment/ransley-md-0
    └─Machine/ransley-md-0-579f95df8b-l7wj8                 True                     2m59s


Providers:

NAMESPACE                          NAME                   TYPE                    PROVIDERNAME  VERSION  WATCHNAMESPACE
capd-system                        infrastructure-docker  InfrastructureProvider  docker        v0.3.23
capi-kubeadm-bootstrap-system      bootstrap-kubeadm      BootstrapProvider       kubeadm       v0.3.23
capi-kubeadm-control-plane-system  control-plane-kubeadm  ControlPlaneProvider    kubeadm       v0.3.23
capi-system                        cluster-api            CoreProvider            cluster-api   v0.3.23
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To configure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl&lt;/code&gt; run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tanzu management-cluster kubeconfig get &amp;lt;MGMT-CLUSTER-NAME&amp;gt; --admin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So in my case:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tanzu management-cluster kubeconfig get ransley --admin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I was then able to run:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which return the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NAME                            STATUS   ROLES                  AGE   VERSION
ransley-control-plane-n7sgp     Ready    control-plane,master   11m   v1.21.5+vmware.1
ransley-md-0-579f95df8b-l7wj8   Ready    &amp;lt;none&amp;gt;                 10m   v1.21.5+vmware.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To create a workload cluster run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tanzu cluster create ransleywl --plan dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command took a few minutes to run and its output was as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Validating configuration...
Warning: Pinniped configuration not found. Skipping pinniped configuration in workload cluster. Please refer to the documentation to check if you can configure pinniped on workload cluster manually
Creating workload cluster 'ransleywl'...
Waiting for cluster to be initialized...
[cluster control plane is still being initialized: WaitingForControlPlane, cluster infrastructure is still being provisioned: WaitingForControlPlane]
cluster control plane is still being initialized: Bootstrapping @ Machine/ransleywl-control-plane-vmhz7
Waiting for cluster nodes to be available...
Waiting for addons installation...
Waiting for packages to be up and running...

Workload cluster 'ransleywl' created
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To verify the cluster started successfully run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tanzu cluster list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which will output the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NAME       NAMESPACE  STATUS   CONTROLPLANE  WORKERS  KUBERNETES        ROLES   PLAN
ransleywl  default    running  1/1           1/1      v1.21.5+vmware.1  &amp;lt;none&amp;gt;  dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To update kubectl for the new cluster run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tanzu cluster kubeconfig get ransleywl --admin
kubectl config use-context ransleywl-admin@ransleywl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To show the pods in the cluster run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl get pods --all-namespaces
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which ouptu the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NAMESPACE      NAME                                                    READY   STATUS    RESTARTS   AGE
kube-system    antrea-agent-52zjf                                      2/2     Running   0          6m5s
kube-system    antrea-agent-6r7cf                                      2/2     Running   0          6m5s
kube-system    antrea-controller-7dc9d9c8d7-9frm2                      1/1     Running   0          6m4s
kube-system    coredns-657879bf57-9fvdm                                1/1     Running   0          13m
kube-system    coredns-657879bf57-wmnct                                1/1     Running   0          13m
kube-system    etcd-ransleywl-control-plane-vmhz7                      1/1     Running   0          13m
kube-system    kube-apiserver-ransleywl-control-plane-vmhz7            1/1     Running   0          13m
kube-system    kube-controller-manager-ransleywl-control-plane-vmhz7   1/1     Running   0          13m
kube-system    kube-proxy-cmq8g                                        1/1     Running   0          13m
kube-system    kube-proxy-n64z9                                        1/1     Running   0          12m
kube-system    kube-scheduler-ransleywl-control-plane-vmhz7            1/1     Running   0          13m
kube-system    metrics-server-649578757b-l844s                         1/1     Running   0          6m13s
tanzu-system   secretgen-controller-f44c8b9c6-b84hw                    1/1     Running   0          7m46s
tkg-system     kapp-controller-f8d47f95c-v9qlf                         1/1     Running   0          12m
tkg-system     tanzu-capabilities-controller-manager-7959d6b44-v96qm   1/1     Running   0          13m
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 25 Feb 2022 00:00:00 -0600</pubDate>
        <link>/blog/ubuntu_20.04_tanzu_install/</link>
        <guid isPermaLink="true">/blog/ubuntu_20.04_tanzu_install/</guid>
      </item>
    
      <item>
        <title>Install Kubectl on Ubuntu 20.04</title>
        <description>&lt;p&gt;To install kubectl on Ubuntu run the following commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo &quot;deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main&quot; | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
sudo apt install -y kubectl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To verify that it works run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And it should respond with something similar to the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl controls the Kubernetes cluster manager.

Find more information at: https://kubernetes.io/docs/reference/kubectl/overview/

Basic Commands (Beginner):
create        Create a resource from a file or from stdin
expose        Take a replication controller, service, deployment or pod and expose it as a new Kubernetes service
run           Run a particular image on the cluster
set           Set specific features on objects

Basic Commands (Intermediate):
explain       Get documentation for a resource
get           Display one or many resources
edit          Edit a resource on the server
delete        Delete resources by file names, stdin, resources and names, or by resources and label selector

Deploy Commands:
rollout       Manage the rollout of a resource
scale         Set a new size for a deployment, replica set, or replication controller
autoscale     Auto-scale a deployment, replica set, stateful set, or replication controller

Cluster Management Commands:
certificate   Modify certificate resources.
cluster-info  Display cluster information
top           Display resource (CPU/memory) usage
cordon        Mark node as unschedulable
uncordon      Mark node as schedulable
drain         Drain node in preparation for maintenance
taint         Update the taints on one or more nodes

Troubleshooting and Debugging Commands:
describe      Show details of a specific resource or group of resources
logs          Print the logs for a container in a pod
attach        Attach to a running container
exec          Execute a command in a container
port-forward  Forward one or more local ports to a pod
proxy         Run a proxy to the Kubernetes API server
cp            Copy files and directories to and from containers
auth          Inspect authorization
debug         Create debugging sessions for troubleshooting workloads and nodes

Advanced Commands:
diff          Diff the live version against a would-be applied version
apply         Apply a configuration to a resource by file name or stdin
patch         Update fields of a resource
replace       Replace a resource by file name or stdin
wait          Experimental: Wait for a specific condition on one or many resources
kustomize     Build a kustomization target from a directory or URL.

Settings Commands:
label         Update the labels on a resource
annotate      Update the annotations on a resource
completion    Output shell completion code for the specified shell (bash, zsh or fish)

Other Commands:
alpha         Commands for features in alpha
api-resources Print the supported API resources on the server
api-versions  Print the supported API versions on the server, in the form of &quot;group/version&quot;
config        Modify kubeconfig files
plugin        Provides utilities for interacting with plugins
version       Print the client and server version information

Usage:
kubectl [flags] [options]

Use &quot;kubectl &amp;lt;command&amp;gt; --help&quot; for more information about a given command.
Use &quot;kubectl options&quot; for a list of global command-line options (applies to all commands).
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 25 Feb 2022 00:00:00 -0600</pubDate>
        <link>/blog/ubuntu_20.04_kubectl_install/</link>
        <guid isPermaLink="true">/blog/ubuntu_20.04_kubectl_install/</guid>
      </item>
    
      <item>
        <title>Install Kubeapps on Kubernetes</title>
        <description>&lt;p&gt;I am mucking around a bit with a homelab and thought I would look into Tanzu and Kubeapps.  To start, I created an absolutely vanilla Ubuntu 20.04 Server instance with 8Gb of Memory and 30Gb of disk.  In then installed some pre-requisite software:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/ubuntu_20.04_tanzu_install/&quot;&gt;Tanzu&lt;/a&gt; or &lt;a href=&quot;/blog/ubuntu_20.04_k3s_install/&quot;&gt;K3S&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/ubuntu_20.04_helm_install/&quot;&gt;Helm&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To install kubeapps run the following commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;helm repo add bitnami https://charts.bitnami.com/bitnami
kubectl create namespace kubeapps
helm install kubeapps --namespace kubeapps bitnami/kubeapps --set useHelm3=true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To create a service account, run the following commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl create serviceaccount kubeapps-operator
kubectl create clusterrolebinding kubeapps-operator --clusterrole=cluster-admin --serviceaccount=default:kubeapps-operator
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then to expose the service so that you can access it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl port-forward --namespace kubeapps service/kubeapps --address 0.0.0.0 8080:80
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then to expose the token for authentication:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl get secret $(kubectl get serviceaccount kubeapps-operator -o jsonpath='{range .secrets[*]}{.name}{&quot;\n&quot;}{end}' | grep kubeapps-operator-token) -o jsonpath='{.data.token}' -o go-template='{{.data.token | base64decode}}' &amp;amp;&amp;amp; echo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then open a browser and navigate to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://tanzu_server:8080&lt;/code&gt; and it will prompt you for a token, enter the token that was created earlier.  You should see a page similiar to the following:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/kubeapps_home.png&quot; alt=&quot;Kubeapps Home&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Fri, 25 Feb 2022 00:00:00 -0600</pubDate>
        <link>/blog/install_kubeapps_on_kubernetes/</link>
        <guid isPermaLink="true">/blog/install_kubeapps_on_kubernetes/</guid>
      </item>
    
      <item>
        <title>Install Helm on Ubuntu 20.04</title>
        <description>&lt;p&gt;I am playing around with a homelab with Kubernetes and Ubuntu and thought I would add helm into the configuration.  To start, I created an absolutely vanilla Ubuntu 20.04 Server instance with 8Gb of Memory and 30Gb of disk.  In then installed some pre-requisite software:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/ubuntu_20.04_docker_install/&quot;&gt;Docker&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/ubuntu_20.04_brew_install/&quot;&gt;Brew&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/ubuntu_20.04_kubectl_install/&quot;&gt;Kubectl&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To install Helm run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install helm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To verify that helm is installed run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;helm version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And it should return something similar to following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;version.BuildInfo{Version:&quot;v3.8.0&quot;, GitCommit:&quot;d14138609b01886f544b2025f5000351c9eb092e&quot;, GitTreeState:&quot;clean&quot;, GoVersion:&quot;go1.17.6&quot;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 25 Feb 2022 00:00:00 -0600</pubDate>
        <link>/blog/ubuntu_20.04_helm_install/</link>
        <guid isPermaLink="true">/blog/ubuntu_20.04_helm_install/</guid>
      </item>
    
      <item>
        <title>Install Docker on Ubuntu 20.04</title>
        <description>&lt;p&gt;There are of course a lot of instructions to do this but I thought I would place the way that I do it for anyone else you may be interested.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt install docker.io
sudo groupadd docker
sudo usermod -aG docker $USER
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Restart the shell, if you are using ubuntu GUI then you will need to logout and log back in.&lt;/p&gt;

&lt;p&gt;To test that it is working run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run hello-world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If this works you should see output similar to the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:97a379f4f88575512824f3b352bc03cd75e239179eea0fecc38e597b2209f49a
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the &quot;hello-world&quot; image from the Docker Hub.
    (amd64)
3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 25 Feb 2022 00:00:00 -0600</pubDate>
        <link>/blog/ubuntu_20.04_docker_install/</link>
        <guid isPermaLink="true">/blog/ubuntu_20.04_docker_install/</guid>
      </item>
    
      <item>
        <title>Install Brew on Ubuntu 20.04</title>
        <description>&lt;p&gt;Now my experience of Brew is mainly related to OSX, but it can be used in linux as well.  To install it run the following commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-get install build-essential
/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;
echo 'eval &quot;$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)&quot;' &amp;gt;&amp;gt; $HOME/.profile
eval &quot;$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To use native tools run the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo chmod o+r /etc/rancher/k3s/k3s.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In order to access kubectl without using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo&lt;/code&gt; run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 25 Feb 2022 00:00:00 -0600</pubDate>
        <link>/blog/ubuntu_20.04_brew_install/</link>
        <guid isPermaLink="true">/blog/ubuntu_20.04_brew_install/</guid>
      </item>
    
      <item>
        <title>CloudWatch Log Retention and Lambda</title>
        <description>&lt;p&gt;One of the great things about Lambda is that when you create a function it automatically creates an associated CloudWatch Log Group so that the output of your function is captured.  The problem is that by default this log group will have a retention of “forever”, which can be costly for a function that is either run a lot or writes a lot of information to CloudWatch.&lt;/p&gt;

&lt;p&gt;To fix this, what you need to do is to update the log retention and the easiest way to do this is through the console, but this obviously isn’t the right way.&lt;/p&gt;

&lt;p&gt;If we assume that you have already run your function and you deployed it using terraform but you want to fix up the log retention then this is how you do it:&lt;/p&gt;

&lt;h3 id=&quot;create-the-cloudwatch-log-group-definition&quot;&gt;Create the CloudWatch Log Group Definition&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;resource &quot;aws_cloudwatch_log_group&quot; &quot;my_log_group&quot; {
    name = &quot;/aws/lambda/my-function&quot;
    retention_in_days = 30
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, if you run this then you will get an error saying that a duplicate resource exists - which it does!&lt;/p&gt;

&lt;h3 id=&quot;import-the-existing-resource-into-terraform&quot;&gt;Import the existing resource into terraform&lt;/h3&gt;

&lt;p&gt;For a terraform resource that is in a module:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;terraform import module.datalake_firehose.aws_cloudwatch_log_group.my_log_group &quot;/aws/lambda/my-function&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For a terraform resource that is not in a module:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;terraform import aws_cloudwatch_log_group.my_log_group &quot;/aws/lambda/my-function&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;execution&quot;&gt;Execution&lt;/h3&gt;

&lt;p&gt;If you then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;terraform apply&lt;/code&gt; then this should update the retention on the CloudWatch log group.&lt;/p&gt;
</description>
        <pubDate>Thu, 29 Oct 2020 00:00:00 -0500</pubDate>
        <link>/blog/cloudwatch-log-retention/</link>
        <guid isPermaLink="true">/blog/cloudwatch-log-retention/</guid>
      </item>
    
      <item>
        <title>AWS Lake Formation</title>
        <description>&lt;p&gt;AWS continues to raise the bar across a whole lot of technology segments and in AWS Lake Formation they have created a one-stop shop for the creation of Data Lakes.  As always, AWS is further abstracting their services to provide more and more customer value.  The evolution of this process can be seen by looking at AWS Glue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This document was written in August 2019 - if you are reading this at some distant time in the future, functionality may (will?) have changed.&lt;/p&gt;

&lt;h2 id=&quot;aws-glue-a-history&quot;&gt;AWS Glue, a History&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Back in the day, when EC2 launched it was a massive game changer.  The ability to be able provision instances in seconds through an API was a revolution.  It was no surprise that many users who used EC2 used it for Hadoop workloads which could benefit from AWS scale to crunch large volumes of data and then terminate when the work had been completed.&lt;/li&gt;
  &lt;li&gt;AWS recognised this need and created &lt;a href=&quot;https://aws.amazon.com/emr/&quot;&gt;EMR&lt;/a&gt; (Elastic Map Reduce).  No longer did we need to configure Hadoop clusters, now all we had to specify through the API was pretty much how many worker nodes we wanted and AWS magic presented us with a cluster with all the node configuration done for us.  &lt;a href=&quot;https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-release-5x.html&quot;&gt;Additional Software&lt;/a&gt; was added in as well allowing to layer additional software onto EMR at instance creation time.&lt;/li&gt;
  &lt;li&gt;Once again, AWS looked at the workloads and realised that many people were using EMR to run Apache Spark jobs.  From this they created Glue, which is effectively a managed Spark implementation (with extensions).  Interestingly, they moved away from a raw CPU pricing mechanism to a DPU (Data Processing Unit), which is 4 CPU’s and 16 GB of RAM but your jobs must run a minimum of 2 DPU’s for a minimum of 10 minutes (see &lt;a href=&quot;https://aws.amazon.com/glue/pricing/&quot;&gt;pricing&lt;/a&gt; for more information).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;back-to-data-lakes&quot;&gt;Back to Data Lakes&lt;/h2&gt;

&lt;p&gt;Obviously, a massive use case with AWS is Data Lakes and data processing platforms generally.  A standard design for the data lakes was to use S3 for storage, EMR/Glue for data processing and the AWS Glue Data Catalog as a metadata store.  AWS has rolled these services into a single unified data lake approach called &lt;a href=&quot;https://aws.amazon.com/lake-formation/&quot;&gt;AWS Lake Foundation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One thing to note about AWS Lake Formation is that while it is a product itself, it is more of an orchestration layer and interface across a whole lot of AWS tools, as shown in the diagram below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/AWS-Lake-Formation.png&quot; alt=&quot;AWS Lake Formation&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can see that Lake Formation contains the building blocks of AWS data platform:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;strong&gt;Source crawlers&lt;/strong&gt; are Glue Crawlers.&lt;/li&gt;
  &lt;li&gt;The &lt;strong&gt;ETL and Data Prep&lt;/strong&gt; are probably provided by Glue Jobs.&lt;/li&gt;
  &lt;li&gt;The &lt;strong&gt;Date catalog&lt;/strong&gt; is probably the Glue Data Catalog.&lt;/li&gt;
  &lt;li&gt;The &lt;strong&gt;Security Settings&lt;/strong&gt; and &lt;strong&gt;Access Control&lt;/strong&gt; are probably provided by a combination of the Glue Data Catalog and AWS IAM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Obviously, the other components are named above.  So what Lake Formation provides is an orchestration and management layer across these services.  Once again, AWS is raising the bar in their platform and making it even more usable for customers.&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;p&gt;AWS Lake Formation has a 3 step setup:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Register your AWS storage.&lt;/li&gt;
  &lt;li&gt;Create a database&lt;/li&gt;
  &lt;li&gt;Grant permissions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/AWS_Lake_Formation_Console.png&quot; alt=&quot;AWS Lake Formation Setup&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;register-you-aws-storage&quot;&gt;Register you AWS storage&lt;/h3&gt;

&lt;p&gt;Interestingly, this requires you to have already created an AWS bucket, it doesn’t create on for you.  For the purposes of this investigation I have created a bucket called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd-lake-formation-demo&lt;/code&gt;, clicking on “Register Location” and enter the path of your bucket - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s3://cmd-lake-formation-demo&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/lake_formation_location.png&quot; alt=&quot;AWS Lake Formation Location&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Clicking “Register Location” creates the location, but click on dashboard again it unfortunately doesn’t show me that a location has been setup.  Anyway, I know that I have setup a location so I will roll onto to step 2 of the setup.&lt;/p&gt;

&lt;h3 id=&quot;create-a-database&quot;&gt;Create a database&lt;/h3&gt;

&lt;p&gt;Once the storage is registered, you need to create a database to store the metadata.  This is done by clicking on the “Create Database” button under stage 2.  If have placed the database into the bucket that I created above and have gone with some sensible values, as shown below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/lake_formation_database.png&quot; alt=&quot;AWS Lake Formation Database&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;grant-permissions&quot;&gt;Grant Permissions&lt;/h3&gt;

&lt;p&gt;Next step is to grant permission, once again I have chosen the database that we have created earlier and gone with sensible defaults:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/lake_formation_permissions.png&quot; alt=&quot;AWS Lake Formation Permissions&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Interestingly, the screenshot above gives a little nugget of information “Active Directory Users and Groups (EMR Beta Only)” - I am guessing that there is an EMR beta that hooks all the software up to Active Directory for those applications that have a user interface - Spark etc, but most importantly Zeppelin and Jupyter!  &lt;strong&gt;Note&lt;/strong&gt;: Another post will be done on this when it becomes Generally Available.&lt;/p&gt;

&lt;p&gt;Ignoring the above, I clicked “Grant” and it came back to the permissions section.  The dashboard is unfortunately still showing the setup but I suppose there will be the need to add additional locations, permissions and databases as the system is used.&lt;/p&gt;

&lt;h2 id=&quot;ingesting-data&quot;&gt;Ingesting Data&lt;/h2&gt;

&lt;p&gt;Lake Formation appears to have three methods for loading data into the lake.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;AWS Glue Crawlers.&lt;/li&gt;
  &lt;li&gt;AWS Glue Jobs.&lt;/li&gt;
  &lt;li&gt;Blueprints&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Obviously the crawlers and jobs are existing technology that has been around for a little while, but the blue prints are interesting…&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/lake_formation_blueprints.png&quot; alt=&quot;AWS Lake Formation Blueprints&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The common ones are going to be the database snapshot and incremental database loads in my experience.  Now looking at the dialog it is clear that this uses AWS Glue for the data movement and hence you will be paying Glue Pricing for the database synchronizations (i.e. 2 * DPU * USD $0.44/hr with a 10 minute minimum).  This means that frequent syncing for your data may get pricey, especially if you are syncing lots of individual and small data sources.&lt;/p&gt;

&lt;p&gt;I shall look into some of these blueprints in a future post.&lt;/p&gt;
</description>
        <pubDate>Tue, 20 Aug 2019 00:00:00 -0500</pubDate>
        <link>/blog/aws-lake-formation/</link>
        <guid isPermaLink="true">/blog/aws-lake-formation/</guid>
      </item>
    
      <item>
        <title>Creating SSM Parameters</title>
        <description>&lt;p&gt;There are many services that I really like in AWS but one of those that doesn’t get a lot of attention is AWS Systems Manager.  While I can’t say that I use all the features regularly of this service, two that I use a lot are the Session Manager and also the parameter store.&lt;/p&gt;

&lt;p&gt;For this post, I will show how to create a value in the parameter store - I use this all the time because it is better than storing passwords in plain text and access to the credential is actually audited.&lt;/p&gt;

&lt;p&gt;To create a value in parameter store you run the following command from the CLI:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;aws ssm put-parameter --name mysecurepassword --type SecureString --value &quot;passw0rd&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will create the password in the Systems Manager Parameter store.  Access to the credential can be controlled by IAM and if you have enabled it you can audit accesses to it via CloudTrail.&lt;/p&gt;
</description>
        <pubDate>Thu, 27 Jun 2019 00:00:00 -0500</pubDate>
        <link>/blog/creating-ssm-paramters/</link>
        <guid isPermaLink="true">/blog/creating-ssm-paramters/</guid>
      </item>
    
      <item>
        <title>S3 Events and Error 403</title>
        <description>&lt;p&gt;I have been performing some data transformations using Lambda and S3 Events and for certain S3 keys I noticed that I was getting an Error 403 in my code:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ERROR] ClientError: An error occurred (403) when calling the HeadObject operation: Forbidden
Traceback (most recent call last):
    File &quot;/var/task/index.py&quot;, line 159, in handler
        if s3_obj.content_length &amp;lt; (400 * MB):
    File &quot;/var/runtime/boto3/resources/factory.py&quot;, line 339, in property_loader
        self.load()
    File &quot;/var/runtime/boto3/resources/factory.py&quot;, line 505, in do_action
        response = action(self, *args, **kwargs)
    File &quot;/var/runtime/boto3/resources/action.py&quot;, line 83, in __call__
        response = getattr(parent.meta.client, operation_name)(**params)
    File &quot;/var/runtime/botocore/client.py&quot;, line 320, in _api_call
        return self._make_api_call(operation_name, kwargs)
    File &quot;/var/runtime/botocore/client.py&quot;, line 623, in _make_api_call
        raise error_class(parsed_response, operation_name)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The interesting thing that came from this was that the error seemed to specifically happen on files that contained special (i.e. non-alphanumeric) characters.  Research indicated that the characters were actually valid - see &lt;a href=&quot;https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html&quot;&gt;https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html&lt;/a&gt; - so it isn’t an issue with the key name itself.&lt;/p&gt;

&lt;p&gt;It turns out that the issue is with the fact that when the S3 Event returns the queue it is URL encoded but when you attempt to use the key in boto3 then it fails.  The solution is to do the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;from urllib import parse
import boto3

S3_RESOURCE = boto3.resource('s3')

def handler(event, context): # pylint: disable=unused-argument
&quot;&quot;&quot;
Lambda entry point.
&quot;&quot;&quot;
for record in event[&quot;Records&quot;]:
    # Lambda struggles to process a file over 400Mb, so am not going to process files larger
    # than that.
    bucket = record[&quot;s3&quot;][&quot;bucket&quot;][&quot;name&quot;]
    key = parse.unquote(record[&quot;s3&quot;][&quot;object&quot;][&quot;key&quot;])
    s3_obj = S3_RESOURCE.Object(bucket, key)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s3_obj&lt;/code&gt; above will then start working.&lt;/p&gt;
</description>
        <pubDate>Wed, 26 Jun 2019 00:00:00 -0500</pubDate>
        <link>/blog/s3-events-and-error-403/</link>
        <guid isPermaLink="true">/blog/s3-events-and-error-403/</guid>
      </item>
    
      <item>
        <title>Backup for SQL Server RDS</title>
        <description>&lt;p&gt;Earlier I &lt;a href=&quot;/2018/11/19/rds-sqlserver-s3.html&quot;&gt;described&lt;/a&gt; how I performed a restore of a database into Amazon RDS for SQL Server.  While I don’t play in SQL Server a lot I had a different requirement from another client a few weeks later that required me to perform a backup of an existing RDS instance.&lt;/p&gt;

&lt;p&gt;Now, for those that have never done it, there is effectively two steps in perform the backup:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Starting the backup process by calling the stored procedure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msdb.dbo.rds_backup_database&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Monitoring the progress of the backup to ensure that it completes successfully by calling the stored procedure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msdb.dbo.rds_task_status&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are a few error conditions that can occur and most of them relate to insufficient permissions on the S3 bucket.&lt;/p&gt;

&lt;p&gt;The following script will perform a synchronous backup of RDS on SQL Server and will wait for the backup to complete before it returns a success.  We ran this code from a GitLab runner.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/7ad214bbf4616788b6afb95aca4114b5.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Some points to note:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Line 3&lt;/strong&gt; needs to be updated for your hostname.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Line 4&lt;/strong&gt; needs to be updated to a user with access to perform a backup of the database.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Line 5&lt;/strong&gt; needs to be updated to be the password for the user defined in &lt;strong&gt;Line 4&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Line 6&lt;/strong&gt; needs to be updated for the ARN of the bucket and key to backup to.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Line 7&lt;/strong&gt; needs to be updated to the database that needs backing up.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Line 10&lt;/strong&gt; actually performs the backup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest of the script after line 10 will check the backup to see if it is successful.  If the backup fails (generally related to S3 permissions) then the exit code should be 1, otherwise the exit code will be 2.  The script expects the backup to complete in 60 minutes.&lt;/p&gt;
</description>
        <pubDate>Sat, 15 Dec 2018 00:00:00 -0600</pubDate>
        <link>/blog/rds-backup/</link>
        <guid isPermaLink="true">/blog/rds-backup/</guid>
      </item>
    
      <item>
        <title>Restoring SQL Server Databases in RDS from S3</title>
        <description>&lt;p&gt;I often don’t play in RDS that much but every once in a while I jump back into it when a clients needs me to do so.  I &lt;strong&gt;know&lt;/strong&gt; that there is a way of restoring a SQL Server database from an S3 location, but for the life of me I could remember how it was done.  For added bonus points I decided that I should try interacting with the database completely without a windows host.&lt;/p&gt;

&lt;p&gt;The trick to ensure that the database can be restored is to assign an Option Group to the RDS Instance:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;RDSOptionGroup:
  Type: &quot;AWS::RDS::OptionGroup&quot;
  Properties:
    EngineName: &quot;sqlserver-web&quot;
    MajorEngineVersion: &quot;13.00&quot;
    OptionGroupDescription: &quot;DB Option Group for nonprod-test-appname&quot;
    OptionConfigurations:
        - OptionName: SQLSERVER_BACKUP_RESTORE
          OptionSettings:
          - Name: IAM_ROLE_ARN
            Value: arn:aws:iam::123456789012:role/client-role-appname-rdsrestore
    Tags:
      - Key: Name
        Value: &quot;nonprod-test-appname&quot;

RDSInstance:
  Type: &quot;AWS::RDS::DBInstance&quot;
  Properties:
    AllowMajorVersionUpgrade: &quot;False&quot;
    AutoMinorVersionUpgrade: &quot;True&quot;
    CopyTagsToSnapshot: &quot;True&quot;
    Engine: sqlserver-web
    EngineVersion: 13.00.4466.4.v1
    DBInstanceClass: &quot;db.t2.small&quot;
    DBSubnetGroupName: !Ref RDSSubnetGroup
    MultiAZ: &quot;False&quot;
    OptionGroupName: !Ref RDSOptionGroup
    PubliclyAccessible: &quot;False&quot;
    Tags:
      - Key: &quot;Name&quot;
        Value: &quot;nonprod-test-app&quot;
    DBInstanceIdentifier: &quot;nonprod-test-app&quot;
    AllocatedStorage: &quot;20&quot;
    BackupRetentionPeriod: &quot;35&quot;
    MasterUserPassword: !Ref MasterUserPassword
    MasterUsername: DBUser
    StorageEncrypted: True
    StorageType: &quot;gp2&quot;
    VPCSecurityGroups:
          sg-0123456780abcdefg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, the bits to note above is the &lt;strong&gt;MajorEngineVersion&lt;/strong&gt; of 13 is actually SQL Server 2016 and the &lt;strong&gt;OptionConfigurations&lt;/strong&gt; points to an IAM role.  It is this IAM role that RDS uses to actually perform the backup or restore operation.  The IAM role needs to be similar to the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;UserRoleAppRdsRestore:
  Type: &quot;AWS::IAM::Role&quot;
  Properties:
    RoleName: &quot;client-role-appname-rdsrestore&quot;
    AssumeRolePolicyDocument:
      Statement:
        - Action: [ &quot;sts:AssumeRole&quot; ]
          Effect: Allow
          Principal:
            Service: [ &quot;rds.amazonaws.com&quot; ]

UserPolicyAppRdsRestore:
  Type: &quot;AWS::IAM::Policy&quot;
  Properties:
    Roles:
        - !Ref UserRoleAppRdsRestore
    PolicyName: &quot;APP-POLICY-RDSRESTORE&quot;
    PolicyDocument:
        Statement:
          - Action:
            - &quot;s3:PutObject&quot;
            - &quot;s3:GetObject&quot;
            - &quot;s3:GetObjectMetaData&quot;
            - &quot;s3:AbortMultipartUpload&quot;
            - &quot;s3:ListMultipartUploadParts&quot;
            - &quot;s3:ListBucket&quot;
            - &quot;s3:GetBucketLocation&quot;
          Effect: Allow
          Resource:
            - &quot;arn:aws:s3:::bucket_name&quot;
            - &quot;arn:aws:s3:::bucket_name/*&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once this is deployed, log into an instance that has network access to the RDS instance and run the following commands (&lt;strong&gt;note&lt;/strong&gt;: This assumes Docker is installed and running on the host):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run -it mcr.microsoft.com/mssql-tools
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then run the following to connect to the host:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sqlcmd -S nonprod-test-app.abcdefghijk.ap-southeast-2.rds.amazonaws.com -U dbusername
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At this point you should be logged into the database, then type the following commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;use master
go
exec msdb.dbo.rds_restore_database @restore_db_name='dbname', @S3_arn_to_restore_from='arn:aws:s3:::bucket_name/folder/db.bak'
go
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To check the status of the restore run the following command inside the same window:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;exec msdb.dbo.rds_task_status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And hopefully your database should be successfully restored.&lt;/p&gt;
</description>
        <pubDate>Mon, 19 Nov 2018 00:00:00 -0600</pubDate>
        <link>/blog/rds-restore-s3/</link>
        <guid isPermaLink="true">/blog/rds-restore-s3/</guid>
      </item>
    
      <item>
        <title>PySpark and Glue together</title>
        <description>&lt;p&gt;I have been playing around with Spark (in EMR) and the Glue Data Catalog a bit and I really like using them together.  The ability of you being able to use EMR to transform the data and then being able to query it in either Spark, Glue or Athena - and through Athena via a JDBC data source is a real winner.&lt;/p&gt;

&lt;p&gt;That said, it isn’t really that clear on how you access and update the Glue Data Catalog from within EMR.  This post will hopefully point you in the right direction.&lt;/p&gt;

&lt;h3 id=&quot;emr-setup&quot;&gt;EMR Setup&lt;/h3&gt;

&lt;p&gt;To work with the Glue Data Catalog the EMR cluster needs to be configured to use it.  There are details for this at AWS, but within automation the following values need to be put into the cluster:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;- Classification: &quot;hive-site&quot;
  Properties:
    'hive.metastore.client.factory.class': &quot;com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory&quot;
- Classification: &quot;spark-hive-site&quot;
  Properties:
    'hive.metastore.client.factory.class': &quot;com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;accessing-glue-tables-from-emr&quot;&gt;Accessing glue tables from EMR&lt;/h3&gt;

&lt;p&gt;To access the tables from within a Spark step you need to instantiate the spark session with the glue catalog:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;spark = SparkSession.builder \
        .appName(job_name) \
        .config(&quot;hive.metastore.client.factory.class&quot;, &quot;com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory&quot;) \
        .enableHiveSupport() \
        .getOrCreate()
    spark.catalog.setCurrentDatabase(&quot;mydatabase&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The database name above is the name of the database within the Glue configurations.&lt;/p&gt;

&lt;p&gt;Now that the Spark Session is setup correctly you can query the glue catalog through Spark SQL:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;spark.sql(&quot;select * from mytable&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note, you don’t need to specify the location of the table, all this information is stored in the Glue Data Catalog.&lt;/p&gt;

&lt;h3 id=&quot;creating-glue-data-catalog-tables-from-spark-on-emr&quot;&gt;Creating Glue Data Catalog Tables from Spark on EMR&lt;/h3&gt;

&lt;p&gt;Now, the prevailing wisdom is that you use the glue crawlers to update the data catalog - my feeling is that where possible the catalog should be updated by the process that is actually landing (or modifying) the data.  The advantage that this gives it allows subsequent steps to execute and use the updated catalog without needed to run a crawler.&lt;/p&gt;

&lt;p&gt;To create the table in glue and save the data into parquet, run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dataframe.write.mode(&quot;overwrite&quot;).format(&quot;parquet&quot;).option(&quot;path&quot;, parquet_path).saveAsTable(glue_table)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;creating-glue-data-catalog-tables-from-glue-jobs&quot;&gt;Creating Glue Data Catalog Tables from Glue Jobs&lt;/h3&gt;

&lt;p&gt;Now, you would think that this is easy… but unfortunately it isn’t.  This will be the subject of another post once I do more research.&lt;/p&gt;
</description>
        <pubDate>Tue, 28 Aug 2018 00:00:00 -0500</pubDate>
        <link>/blog/spark-and-glue/</link>
        <guid isPermaLink="true">/blog/spark-and-glue/</guid>
      </item>
    

    
      
        
      
    
      
    
      
        
          <item>
            <title></title>
            <description>&lt;h3&gt;   &lt;/h3&gt;

&lt;div id=&quot;categories&quot;&gt;

  &lt;div class=&quot;category-box&quot;&gt;
    
    &lt;div id=&quot;#aws&quot;&gt;&lt;/div&gt;
    &lt;h4 class=&quot;category-head&quot;&gt;&lt;a href=&quot;/blog/categories/aws&quot;&gt;aws&lt;/a&gt;&lt;/h4&gt;
    &lt;a name=&quot;aws&quot;&gt;&lt;/a&gt;
     
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/cloudwatch-log-retention/&quot;&gt;CloudWatch Log Retention and Lambda&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/aws-lake-formation/&quot;&gt;AWS Lake Formation&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/creating-ssm-paramters/&quot;&gt;Creating SSM Parameters&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/s3-events-and-error-403/&quot;&gt;S3 Events and Error 403&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/rds-backup/&quot;&gt;Backup for SQL Server RDS&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/rds-restore-s3/&quot;&gt;Restoring SQL Server Databases in RDS from S3&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/spark-and-glue/&quot;&gt;PySpark and Glue together&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    

  &lt;/div&gt;

  &lt;div class=&quot;category-box&quot;&gt;
    
    &lt;div id=&quot;#ubuntu&quot;&gt;&lt;/div&gt;
    &lt;h4 class=&quot;category-head&quot;&gt;&lt;a href=&quot;/blog/categories/ubuntu&quot;&gt;ubuntu&lt;/a&gt;&lt;/h4&gt;
    &lt;a name=&quot;ubuntu&quot;&gt;&lt;/a&gt;
     
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/ubuntu_20.04_kubectl_install/&quot;&gt;Install Kubectl on Ubuntu 20.04&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/ubuntu_20.04_helm_install/&quot;&gt;Install Helm on Ubuntu 20.04&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/ubuntu_20.04_docker_install/&quot;&gt;Install Docker on Ubuntu 20.04&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/ubuntu_20.04_brew_install/&quot;&gt;Install Brew on Ubuntu 20.04&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    

  &lt;/div&gt;

  &lt;div class=&quot;category-box&quot;&gt;
    
    &lt;div id=&quot;#kubernetes&quot;&gt;&lt;/div&gt;
    &lt;h4 class=&quot;category-head&quot;&gt;&lt;a href=&quot;/blog/categories/kubernetes&quot;&gt;kubernetes&lt;/a&gt;&lt;/h4&gt;
    &lt;a name=&quot;kubernetes&quot;&gt;&lt;/a&gt;
     
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/ubuntu_20.04_k3s_install/&quot;&gt;Install K3S on Ubuntu 20.04&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/ubuntu_20.04_tanzu_install/&quot;&gt;Install Tanzu on Ubuntu 20.04&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    
    &lt;article class=&quot;center&quot;&gt;
      &lt;h6&gt;&lt;a href=&quot;/blog/install_kubeapps_on_kubernetes/&quot;&gt;Install Kubeapps on Kubernetes&lt;/a&gt;&lt;/h6&gt;
    &lt;/article&gt;


    

  &lt;/div&gt;

&lt;/div&gt;

</description>
            <link>/blog/categories/</link>
          </item>
        
      
    
      
        
          <item>
            <title>AWS</title>
            <description>&lt;h5&gt; Posts by Category : AWS &lt;/h5&gt;

&lt;div class=&quot;card&quot;&gt;

 &lt;li class=&quot;category-posts&quot;&gt;&lt;span&gt;29 Oct 2020&lt;/span&gt; &amp;nbsp; &lt;a href=&quot;/blog/cloudwatch-log-retention/&quot;&gt;CloudWatch Log Retention and Lambda&lt;/a&gt;&lt;/li&gt;

 &lt;li class=&quot;category-posts&quot;&gt;&lt;span&gt;20 Aug 2019&lt;/span&gt; &amp;nbsp; &lt;a href=&quot;/blog/aws-lake-formation/&quot;&gt;AWS Lake Formation&lt;/a&gt;&lt;/li&gt;

 &lt;li class=&quot;category-posts&quot;&gt;&lt;span&gt;27 Jun 2019&lt;/span&gt; &amp;nbsp; &lt;a href=&quot;/blog/creating-ssm-paramters/&quot;&gt;Creating SSM Parameters&lt;/a&gt;&lt;/li&gt;

 &lt;li class=&quot;category-posts&quot;&gt;&lt;span&gt;26 Jun 2019&lt;/span&gt; &amp;nbsp; &lt;a href=&quot;/blog/s3-events-and-error-403/&quot;&gt;S3 Events and Error 403&lt;/a&gt;&lt;/li&gt;

 &lt;li class=&quot;category-posts&quot;&gt;&lt;span&gt;15 Dec 2018&lt;/span&gt; &amp;nbsp; &lt;a href=&quot;/blog/rds-backup/&quot;&gt;Backup for SQL Server RDS&lt;/a&gt;&lt;/li&gt;

 &lt;li class=&quot;category-posts&quot;&gt;&lt;span&gt;19 Nov 2018&lt;/span&gt; &amp;nbsp; &lt;a href=&quot;/blog/rds-restore-s3/&quot;&gt;Restoring SQL Server Databases in RDS from S3&lt;/a&gt;&lt;/li&gt;

 &lt;li class=&quot;category-posts&quot;&gt;&lt;span&gt;28 Aug 2018&lt;/span&gt; &amp;nbsp; &lt;a href=&quot;/blog/spark-and-glue/&quot;&gt;PySpark and Glue together&lt;/a&gt;&lt;/li&gt;

&lt;/div&gt;
</description>
            <link>/blog/categories/aws/</link>
          </item>
        
      
    
      
    
      
    
      
    
      
        
          <item>
            <title>kubernetes</title>
            <description>&lt;h5&gt; Posts by Category : {{ page.title }} &lt;/h5&gt;

&lt;div class=&quot;card&quot;&gt;
{% for post in site.categories.kubernetes %}
 &lt;li class=&quot;category-posts&quot;&gt;&lt;span&gt;{{ post.date | date_to_string }}&lt;/span&gt; &amp;nbsp; &lt;a href=&quot;{{ post.url }}&quot;&gt;{{ post.title }}&lt;/a&gt;&lt;/li&gt;
{% endfor %}
&lt;/div&gt;</description>
            <link>/blog/categories/kubernetes/</link>
          </item>
        
      
    
      
    
      
        
          <item>
            <title>ubuntu</title>
            <description>&lt;h5&gt; Posts by Category : {{ page.title }} &lt;/h5&gt;

&lt;div class=&quot;card&quot;&gt;
{% for post in site.categories.ubuntu %}
 &lt;li class=&quot;category-posts&quot;&gt;&lt;span&gt;{{ post.date | date_to_string }}&lt;/span&gt; &amp;nbsp; &lt;a href=&quot;{{ post.url }}&quot;&gt;{{ post.title }}&lt;/a&gt;&lt;/li&gt;
{% endfor %}
&lt;/div&gt;</description>
            <link>/blog/categories/ubuntu/</link>
          </item>
        
      
    
      
    
      
    
      
    
      
    
      
    
      
    

  </channel>
</rss>