How to Deploy Tanzu Kubernetes Grid Cluster on VMware vSphere Infrastructure in 9 Steps

Dawood Munavar Aug 06 - 11 min read

Audio : Listen to This Blog.

TKG is a CNCF-certified Kubernetes distribution. This blog post helps you to create Tanzu Kubernetes Grid Cluster running on vSphere 6.7 Update 3 infrastructure.

Pre-requisites:

  • vSphere 6.7 Update 3 infrastructure (Minimum supported version).
  • Resource pool in vSphere to deploy the Tanzu Kubernetes Grid Instance (TKG).
  • VM folder in vSphere to collect the Tanzu Kubernetes Grid VMs (TKG).
  • Linux VM to manage kubectl and to install Tanzu Kubernetes Grid CLI.
  • A network segment with DHCP enabled.
  • Download TKG OVA (kube, haproxy) & TKG CLI from – https://my.vmware.com/web/vmware/downloads/details?downloadGroup=TKG-112&productId=988

Software specifications used:

  • vSphere 6.7 – Version 6.7.0.40000 Build 14368061
  • ESXi host – version 6.7
  • Linux VM – used CentOS 7.4 VM with DHCP enabled on the network (with 8GB RAM)
  • HA proxy OVA – v.1.2.4
  • Photon appliance kube OVA – v1.18.3
  • Installed TKG CLI on Linux VM- tkg-linux-amd64-v1.1.2-vmware.1.gz
  • VMFS6 datastore – SAN FC volume created from FlashArray

STEP 1: Installing Kubectl, Docker On Linux VM

[root@localhost ~]# curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl

% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                             Dload  Upload   Total   Spent    Left  Speed
100 41.9M  100 41.9M    0     0  63.7M      0 --:--:-- --:--:-- --:--:-- 63.7M
[root@localhost ~]# chmod +x kubectl
[root@localhost ~]# mv kubectl /usr/local/bin
[root@localhost ~]# yum install docker
[root@localhost ~]# systemctl start docker
[root@localhost ~]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

STEP 2: Install TKG CLI on Linux VM

[root@localhost ~]# gunzip tkg-linux-amd64-v1.1.2-vmware.1.gz
[root@localhost ~]# mv tkg-linux-amd64-v1.1.2-vmware.1 /usr/local/bin/tkg
[root@localhost ~]# chmod +x /usr/local/bin/tkg
[root@localhost ~]# tkg version
Client:
Version: v1.1.2
Git commit: c1db5bed7bc95e2ba32cf683c50525cdff0f2396

STEP 3: Create an SSH Key Pair ON LINUX VM

[root@localhost ~]# ssh-keygen -t rsa -b 4096 -C "[email protected]"
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:

SHA256:OEUW0NgtXubzbeuSnATjExnVhSdBr56Dd3VH3mOGzhw [email protected]
The key's randomart image is:
+---[RSA 4096]----+
|      .=+o ..oo+.|
|      .o+ =   +..|
|       ..= o   oo|
|       o. B   .+.|
|      o S. * E.+*|
|       .  o *o*.=|
|           +.B=..|
|            =..o |
|             o.  |
+----[SHA256]-----+


[root@localhost ~]# cat /root/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDveWLrtmqU+3ueNVrKcxZjEKuME3kmOa60iVGofTIE6X6kEzarSWEU1vVN2FWhO1D1sT0YooU/TiX2wODvkcKKdBBBQOP/
45lrvosVbOUM7LpprOOjfxwckXTbxPPune8toHX7MfjOTRAagyNUwX9Wztf2AhfzImD8tQudixNc+jCUrfICSxyfbqwBX2YbNQnAaQypkL+yuKjHoEjK+8juCU6SU/e42aWP
uI7U9U8LkGAxOaMQ93LshRokjFfFoShZjLgxxNrwvmBmoL5IegqOLsd8I7ZigKCkyGJk2PYvNfB6G/82udE6GdqLedwcilTVO6PkZXLXIVTBuk/cNruhYBcdgt+gfAyLWf4n
U+QKO9m6Enp6JvJVGyg6YBRs8N+i5QQrWprhxYzF/QnMOePdRbD4rpZsvH8KQg12/rrtLgLPzDcr2c7Efs+d8Vaa3jg0ZhHmaXSqaOcbylcxxSR+CGHfccpRs1kPlmtBkr2c
FYaAFLY5jgF2UXy9lSiwGr1waY/CFxI10lHqL7Wv5nFm9DiujHyuLSnQ5Kk1q5+M7EsFgI/I+lk3edI/1+c1LfJSspk6dgO4LKtw2sd+MrgDFLaxFpnWFXnaou/faAc3xCUb
Aj8zcYtUAgFdKQZEQ92uACApR4oTInk9OK0KvuDrMuuQLX9HCGunH7rkS3ADhQ== [email protected]


[root@localhost ~]# ssh-agent /bin/sh
sh-4.2# ssh-add ~/.ssh/id_rsa
Enter passphrase for /root/.ssh/id_rsa:
Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)

sh-4.2# exit

STEP 4: Deploy OVAs & Create Templates in vSphere 6.7 U3

Convert both ova (haproxy, kube) to templates and put them into a VM folder.

Here are the high-level steps:

  • 1. In the vSphere Client, right-click on cluster & select Deploy OVF template.
  • 2. Choose Local file, click the button to upload files, and navigate to the photon-3-kube-v1.18.3-vmware.1.ova file on your local machine.
  • 3. Choose the appliance name
  • 4. Choose the destination as VM folder – TKG1 (VM folder created as a part of pre-requisites)
  • 5. Choose the destination as resource pool – TKG1 (Resource pool created as a part of pre-requisites)
  • 6. Accept EULA
  • 7. Select the datastore as (VMFS6 Datastore created as a part of software specifications)
  • 8. Select the network for the VM to connect (Network segment created as a part of software specifications
  • 9. Click Finish to deploy the VM
  • 10. Right-click on the VM, select Template and click on Convert to Template
  • 11. Follow the same step for haproxy OVA – photon-3-haproxy-v1.2.4-vmware.1.ova

Screenshot below:

Here’s an example of my vSphere, where I have created VM folder as TKG, and TKG1 – where both have kube and haproxy templates added to it.

STEP 5: Deploy Tanzu Kubernetes Grid Management cluster

First generate the config.yaml file on Linux VM:

[root@localhost ~]# tkg get management-cluster
 MANAGEMENT-CLUSTER-NAME  CONTEXT-NAME
[root@localhost ~]# cd .tkg/
[root@localhost .tkg]# ls -a
.  ..  bom  config.yaml  providers

Now edit the config.yaml file in that folder:

Example of my full YAML file:

cert-manager-timeout: 30m0s
overridesFolder: /root/.tkg/overrides
NODE_STARTUP_TIMEOUT: 20m
BASTION_HOST_ENABLED: "true"
providers:
  - name: cluster-api
    url: /root/.tkg/providers/cluster-api/v0.3.6/core-components.yaml

 type: CoreProvider
- name: aws
url: /root/.tkg/providers/infrastructure-aws/v0.5.4/infrastructure-components.yaml
type: InfrastructureProvider
- name: vsphere
url: /root/.tkg/providers/infrastructure-vsphere/v0.6.5/infrastructure-components.yaml
type: InfrastructureProvider
- name: tkg-service-vsphere
url: /root/.tkg/providers/infrastructure-tkg-service-vsphere/v1.0.0/unused.yaml
type: InfrastructureProvider
- name: kubeadm
url: /root/.tkg/providers/bootstrap-kubeadm/v0.3.6/bootstrap-components.yaml
type: BootstrapProvider
- name: kubeadm
url: /root/.tkg/providers/control-plane-kubeadm/v0.3.6/control-plane-components.yaml
type: ControlPlaneProvider
images:
    all:
        repository: registry.tkg.vmware.run/cluster-api
    cert-manager:
        repository: registry.tkg.vmware.run/cert-manager
        tag: v0.11.0_vmware.1
VSPHERE_SERVER: munavarvcsa.init82d-22.dev.purestorage.com
VSPHERE_USERNAME: [email protected]
VSPHERE_PASSWORD: "P@ssw0rd"
VSPHERE_DATACENTER: munavar
VSPHERE_DATASTORE: wsame_large
VSPHERE_NETWORK: SST-C14-sst01-VLAN2176
VSPHERE_RESOURCE_POOL: TKG1
VSPHERE_FOLDER: TKG1
VSPHERE_TEMPLATE: photon-3-kube-v1.18.3-vmware.1
VSPHERE_HAPROXY_TEMPLATE: photon-3-haproxy-v1.2.4-vmware.1
VSPHERE_DISK_GIB: "30"
VSPHERE_NUM_CPUS: "2"
VSPHERE_MEM_MIB: "4096"
VSPHERE_SSH_AUTHORIZED_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDveWLrtmqU+3ueNVrKcxZjEKuME3kmOa60iVGofTIE6X6kEzarSWEU1vVN2FWhO1D1sT0YooU/TiX2wODvkcKKdBBBQOP/45lrvosVbOUM7LpprOOjfxwckXTbxPPune8toHX7MfjOTRAagyNUwX9Wztf2AhfzImD8tQudixNc+jCUrfICSxyfbqwBX2YbNQnAaQypkL+yuKjHoEjK+8juCU6SU/e42aWPuI7U9U8LkGAxOaMQ93LshRokjFfFoShZjLgxxNrwvmBmoL5IegqOLsd8I7ZigKCkyGJk2PYvNfB6G/82udE6GdqLedwcilTVO6PkZXLXIVTBuk/cNruhYBcdgt+gfAyLWf4nU+QKO9m6Enp6JvJVGyg6YBRs8N+i5QQrWprhxYzF/QnMOePdRbD4rpZsvH8KQg12/rrtLgLPzDcr2c7Efs+d8Vaa3jg0ZhHmaXSqaOcbylcxxSR+CGHfccpRs1kPlmtBkr2cFYaAFLY5jgF2UXy9lSiwGr1waY/CFxI10lHqL7Wv5nFm9DiujHyuLSnQ5Kk1q5+M7EsFgI/I+lk3edI/1+c1LfJSspk6dgO4LKtw2sd+MrgDFLaxFpnWFXnaou/faAc3xCUbAj8zcYtUAgFdKQZEQ92uACApR4oTInk9OK0KvuDrMuuQLX9HCGunH7rkS3ADhQ== [email protected]"
SERVICE_CIDR: 100.64.0.0/13
CLUSTER_CIDR: 100.96.0.0/11
release:
    version: v1.1.2

Now, kick off deploy!

[root@localhost .tkg]# tkg init --infrastructure=vsphere --name=munavar-tkg-esx --plan=prod --config ./config.yaml
Logs of the command execution can also be found at: /tmp/tkg-20200728T123415379585498.log

Validating the pre-requisites...

Setting up management cluster...
Validating configuration...
Using infrastructure provider vsphere:v0.6.5
Generating cluster configuration...
Setting up bootstrapper...
Bootstrapper created. Kubeconfig: /root/.kube-tkg/tmp/config_9kc6cpAY
Installing providers on bootstrapper...
Fetching providers
Installing cert-manager
Waiting for cert-manager to be available...
Installing Provider="cluster-api" Version="v0.3.6" TargetNamespace="capi-system"
Installing Provider="bootstrap-kubeadm" Version="v0.3.6" TargetNamespace="capi-kubeadm-bootstrap-system"
Installing Provider="control-plane-kubeadm" Version="v0.3.6" TargetNamespace="capi-kubeadm-control-plane-system"
Installing Provider="infrastructure-vsphere" Version="v0.6.5" TargetNamespace="capv-system"
Start creating management cluster...
Saving management cluster kuebconfig into /root/.kube/config
Installing providers on management cluster...
Fetching providers
Installing cert-manager
Waiting for cert-manager to be available...
Installing Provider="cluster-api" Version="v0.3.6" TargetNamespace="capi-system"
Installing Provider="bootstrap-kubeadm" Version="v0.3.6" TargetNamespace="capi-kubeadm-bootstrap-system"
Installing Provider="control-plane-kubeadm" Version="v0.3.6" TargetNamespace="capi-kubeadm-control-plane-system"
Installing Provider="infrastructure-vsphere" Version="v0.6.5" TargetNamespace="capv-system"
Waiting for the management cluster to get ready for move...
Moving all Cluster API objects from bootstrap cluster to management cluster...
Performing move...
Discovering Cluster API objects
Moving Cluster API objects Clusters=1
Creating objects in the target cluster
Deleting objects from the source cluster
Context set for management cluster munavar-tkg-esx as 'munavar-tkg-esx-admin@munavar-tkg-esx'.

Management cluster created!

You can now create your first workload cluster by running the following:

  tkg create cluster [name] --kubernetes-version=[version] --plan=[plan]

STEP 6: Management cluster is done!

You will start to see the VMs appear on resource pool:

STEP 7: You can verify that all nodes are up & running by running the command

[root@localhost .tkg]# kubectl get nodes
NAME                                    STATUS   ROLES    AGE    VERSION
munavar-tkg-esx-control-plane-6c48c     Ready    master   119m   v1.18.3+vmware.1
munavar-tkg-esx-control-plane-9jmqr     Ready    master   121m   v1.18.3+vmware.1
munavar-tkg-esx-control-plane-r7ggw     Ready    master   117m   v1.18.3+vmware.1
munavar-tkg-esx-md-0-589989d789-bmd7b   Ready       119m   v1.18.3+vmware.1

[root@localhost ~]# kubectl get nodes -o wide
NAME                                    STATUS   ROLES    AGE   VERSION            INTERNAL-IP    EXTERNAL-IP    OS-IMAGE                 KERNEL-VERSION   CONTAINER-RUNTIME
munavar-tkg-esx-control-plane-6c48c     Ready    master   22h   v1.18.3+vmware.1   10.20.186.48   10.20.186.48   VMware Photon OS/Linux   4.19.126-1.ph3   containerd://1.3.4
munavar-tkg-esx-control-plane-9jmqr     Ready    master   22h   v1.18.3+vmware.1   10.20.186.47   10.20.186.47   VMware Photon OS/Linux   4.19.126-1.ph3   containerd://1.3.4
munavar-tkg-esx-control-plane-r7ggw     Ready    master   22h   v1.18.3+vmware.1   10.20.186.50   10.20.186.50   VMware Photon OS/Linux   4.19.126-1.ph3   containerd://1.3.4
munavar-tkg-esx-md-0-589989d789-bmd7b   Ready       22h   v1.18.3+vmware.1   10.20.186.49   10.20.186.49   VMware Photon OS/Linux   4.19.126-1.ph3   containerd://1.3.4

STEP 8: Deploy Tanzu Kubernetes Grid Workload cluster

[root@localhost ~]# tkg create cluster munavar --plan=prod
Logs of the command execution can also be found at: /tmp/tkg-20200729T100156091996395.log
Validating configuration...
Creating workload cluster 'munavar'...
Waiting for cluster to be initialized...
Waiting for cluster nodes to be available...
Workload cluster 'munavar' created

[root@localhost ~]# tkg get clusters
 NAME     NAMESPACE  STATUS   CONTROLPLANE  WORKERS  KUBERNETES
 munavar  default    running  3/3           3/3      v1.18.3+vmware.1

[root@localhost ~]# tkg get credentials munavar
Credentials of workload cluster 'munavar' have been saved
You can now access the cluster by running 'kubectl config use-context munavar-admin@munavar'

[root@localhost ~]# kubectl config get-contexts
CURRENT   NAME                                    CLUSTER           AUTHINFO                
          munavar-admin@munavar                   munavar           munavar-admin
*         munavar-tkg-esx-admin@munavar-tkg-esx   munavar-tkg-esx   munavar-tkg-esx-admin

[root@localhost ~]# kubectl config use-context munavar-admin@munavar
Switched to context "munavar-admin@munavar".

[root@localhost ~]# kubectl get nodes -o wide
NAME                            STATUS   ROLES    AGE   VERSION            INTERNAL-IP    EXTERNAL-IP    OS-IMAGE                 KERNEL-VERSION   CONTAINER-RUNTIME
munavar-control-plane-crrzm     Ready    master   42m   v1.18.3+vmware.1   10.20.186.55   10.20.186.55   VMware Photon OS/Linux   4.19.126-1.ph3   containerd://1.3.4
munavar-control-plane-ns49q     Ready    master   43m   v1.18.3+vmware.1   10.20.186.52   10.20.186.52   VMware Photon OS/Linux   4.19.126-1.ph3   containerd://1.3.4
munavar-control-plane-vkcpb     Ready    master   39m   v1.18.3+vmware.1   10.20.186.57   10.20.186.57   VMware Photon OS/Linux   4.19.126-1.ph3   containerd://1.3.4
munavar-md-0-7f5b7745dc-4n296   Ready       42m   v1.18.3+vmware.1   10.20.186.56   10.20.186.56   VMware Photon OS/Linux   4.19.126-1.ph3   containerd://1.3.4
munavar-md-0-7f5b7745dc-9jbqz   Ready       42m   v1.18.3+vmware.1   10.20.186.53   10.20.186.53   VMware Photon OS/Linux   4.19.126-1.ph3   containerd://1.3.4
munavar-md-0-7f5b7745dc-r5rvz   Ready       42m   v1.18.3+vmware.1   10.20.186.54   10.20.186.54   VMware Photon OS/Linux   4.19.126-1.ph3   containerd://1.3.4

You will start to see the VMs appear on resource pool:

And voila!

STEP 9: Let us deploy an Nginx application on the TKG cluster:

[root@localhost ~]# kubectl create deployment nginx --image=nginx
deployment.apps/nginx created

[root@localhost ~]# kubectl create service nodeport nginx --tcp=80:80
service/nginx created

[root@localhost ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP      100.64.0.1              443/TCP        4h7m
nginx        NodePort    100.71.36.242            80:32634/TCP    8s

[root@localhost ~]# curl munavar-md-0-7f5b7745dc-4n296:32634

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/" style="color:#00aeff;">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/" style="color:#00aeff;">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

References:

  1. https://www.codyhosterman.com/2020/07/deploying-vmware-tanzu-kubernetes-grid-with-pure-storage-vvols-part-i-deploy-tkg-on-vsphere/
  2. https://davidstamen.com/deploying-tkg-on-vsphere/

Challenges faced while deploying TKG:

  • 1. Initially, I deployed TKG on vSphere 6.7 U1 but the configuration failed while trying to deploy TKG management cluster, with an error “Minimum supported version for TKG deployment as vSphere 6.7 U3”
  • 2. On the config.yaml, we have specific parameters SERVICE_CIDR, CLUSTER_CIDR, make sure to go with the defaults (100.64.0.0/13, 100.96.0.0/11) unless they are unavailable for whatever reasons.
  • 3. Please ensure the formatting of things in the config.yaml are correctly aligned.

If you follow these steps, you will find it easy to deploy Tanzu Kubernetes Grid Cluster on VMware vSphere infrastructure. If you’d like to know more about TKG, feel free to drop a note in the comments.

Leave a Reply