TKG Shared AVI SE Group using Antrea NodePortLocal
TKG Shared AVI SE Group using Antrea NodePortLocal
Introduction
If you have been following my blogs on TKG with AKO or have been testing AKO, you will soon realize you will need multiple AVI SE Groups, one AVI SE Group per Kubernetes Cluster. So with TKG and powered by ClusterAPI, you can create Kuberetes cluster really easily, and thus if you want to use AKO, you will quickly found out that you will need to create multiple AVI SE Groups.
Certain customers and also colleagues have brought this issue up and especially with smaller environments or clusters with little requirements on the throughput/transactions on the Ingress or LB, this 1:1 mapping of Kubernetes cluster and AVI SE Group which causes alot of AVI SE Groups being created becomes a manageability problem.
Technical Limitation
In AVI, there are a few modes which you can utilize.
Mode 1: ClusterIP mode ClusterIP mode provides direct connectivity to the K8s pods, which means you need connect the AVI SE interface to the worker nodes network. However, there is a restriction of a SE group per cluster which means you will need more resources and AVI licenses.
Node 2: NodePort mode NodePort resolves the issue for needing a SE group per TKG cluster, but what happens under the hood is that a kube-proxy is created on each and every workload node even if the pod does not exist in it, and there is no need for direct connectivity. The user also needs to change their manifests to use NodePort which sometimes can be an inconvenience.
Solution
Mode 3: NodePortLocal NodePortLocal is the best of both worlds, still use ClusterIP in your manifest, but rather than kube-proxy being utilised, there is a single iptables entry per pod which means direct connectivity to each pod for monitoring. NodePortLocal also resolves the issue for needing a SE group per TKG cluster.
Software Versions Used
Software | Versions |
---|---|
TKG-m | 1.4 |
AKO | 1.5.2 |
AMKO | 1.5.2 |
AVI Controller | 20.1.6 |
Antrea | 0.13.3-7ad64b3 |
Screenshots
Application Dashboard View. We can see that I have 2 TKG clusters, and the worker nodes are on the same subnet but different IP address. You can also see the NodePortLocal in action where you can see the different NodePorts being used.
Infrastructure SE View You can see that the Ingress Virtual Services for tkgm-guest1 and tkgm-guest2 are on the same Service Engine.
[root@localhost ~]# k get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hello-kubernetes-594948df-5hg52 1/1 Running 0 12d 100.96.1.21 tkgm-guest1-md-0-57b86cd777-bmzsf <none> <none>
hello-kubernetes-594948df-6tfxn 1/1 Running 0 12d 100.96.1.22 tkgm-guest1-md-0-57b86cd777-bmzsf <none> <none>
hello-kubernetes-594948df-sl54n 1/1 Running 0 12d 100.96.1.20 tkgm-guest1-md-0-57b86cd777-bmzsf <none> <none>
[root@localhost ~]# k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-kubernetes ClusterIP 100.66.53.34 <none> 80/TCP 12d
kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 12d
[root@localhost ~]# k get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
tkgm-guest1-control-plane-dn8z5 Ready control-plane,master 12d v1.21.2+vmware.1 10.114.1.56 10.114.1.56 VMware Photon OS/Linux 4.19.198-1.ph3 containerd://1.4.6
tkgm-guest1-md-0-57b86cd777-58tpl Ready <none> 12d v1.21.2+vmware.1 10.114.1.59 10.114.1.59 VMware Photon OS/Linux 4.19.198-1.ph3 containerd://1.4.6
tkgm-guest1-md-0-57b86cd777-bmzsf Ready <none> 12d v1.21.2+vmware.1 10.114.1.57 10.114.1.57 VMware Photon OS/Linux 4.19.198-1.ph3 containerd://1.4.6
[root@localhost ~]#
[root@localhost ~]# k get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hello-kubernetes-594948df-lfpcg 1/1 Running 0 12d 100.96.2.8 tkgm-guest2-md-0-6545677fcb-thz7k <none> <none>
hello-kubernetes-594948df-wnkkm 1/1 Running 0 12d 100.96.2.10 tkgm-guest2-md-0-6545677fcb-thz7k <none> <none>
hello-kubernetes-594948df-x6llw 1/1 Running 0 12d 100.96.2.9 tkgm-guest2-md-0-6545677fcb-thz7k <none> <none>
[root@localhost ~]# k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-kubernetes ClusterIP 100.66.141.137 <none> 80/TCP 12d
kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 12d
[root@localhost ~]# k get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
tkgm-guest2-control-plane-fmj7r Ready control-plane,master 12d v1.21.2+vmware.1 10.114.1.16 10.114.1.16 VMware Photon OS/Linux 4.19.198-1.ph3 containerd://1.4.6
tkgm-guest2-md-0-6545677fcb-thz7k Ready <none> 12d v1.21.2+vmware.1 10.114.1.65 10.114.1.65 VMware Photon OS/Linux 4.19.198-1.ph3 containerd://1.4.6
tkgm-guest2-md-0-6545677fcb-wp8cg Ready <none> 12d v1.21.2+vmware.1 10.114.1.17 10.114.1.17 VMware Photon OS/Linux 4.19.198-1.ph3 containerd://1.4.6
[root@localhost ~]#
TKG-m Configuration for NodePortLocal
There is nothing particular to be configured on the TKG-m side. with TKG-m 1.4, Antrea is the default CNI and the Antrea version that comes with it which is 0.13.x already support NodePortLocal.
You can check whether NodePortLocal is enabled by checking the configmap.
[root@localhost ~]# k get configmap antrea-config-ctb8mftc58 -n kube-system -oyaml
apiVersion: v1
data:
antrea-agent.conf: |
featureGates:
AntreaProxy: true
EndpointSlice: false
Traceflow: true
NodePortLocal: true
AntreaPolicy: true
FlowExporter: false
NetworkPolicyStats: false
trafficEncapMode: encap
noSNAT: false
serviceCIDR: 100.64.0.0/13
tlsCipherSuites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384
Reference: https://antrea.io/docs/main/docs/node-port-local/
How to configure AKO to use NodePortLocal?
You can refer to my TKGm 1.4 AMKO Install repo for the sample values.yaml and install scripts for TKG-m, AKO and AMKO. https://github.com/vincenthanjs/tkgm1.4-amko-install
values.yaml for TKG-m Cluster 1 AKO Install. Things to note are the cniPlugin: antrea and the serviceEngineGroupName.
# Default values for ako.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: projects.registry.vmware.com/ako/ako
pullPolicy: IfNotPresent
### This section outlines the generic AKO settings
AKOSettings:
logLevel: WARN # enum: INFO|DEBUG|WARN|ERROR
fullSyncFrequency: '1800' # This frequency controls how often AKO polls the Avi controller to update itself with cloud configurations.
apiServerPort: 8080 # Internal port for AKO's API server for the liveness probe of the AKO pod default=8080
deleteConfig: 'false' # Has to be set to true in configmap if user wants to delete AKO created objects from AVI
disableStaticRouteSync: 'false' # If the POD networks are reachable from the Avi SE, set this knob to true.
clusterName: tkgm-guest1 # A unique identifier for the kubernetes cluster, that helps distinguish the objects for this cluster in the avi controller. // MUST-EDIT
cniPlugin: 'antrea' # Set the string if your CNI is calico or openshift. enum: calico|canal|flannel|openshift|antrea|ncp
enableEVH: false # This enables the Enhanced Virtual Hosting Model in Avi Controller for the Virtual Services
layer7Only: false # If this flag is switched on, then AKO will only do layer 7 loadbalancing.
# NamespaceSelector contains label key and value used for namespacemigration
# Same label has to be present on namespace/s which needs migration/sync to AKO
namespaceSelector:
labelKey: ''
labelValue: ''
servicesAPI: false # Flag that enables AKO in services API mode: https://kubernetes-sigs.github.io/service-apis/. Currently implemented only for L4. This flag uses the upstream GA APIs which are not backward compatible
# with the advancedL4 APIs which uses a fork and a version of v1alpha1pre1
### This section outlines the network settings for virtualservices.
NetworkSettings:
## This list of network and cidrs are used in pool placement network for vcenter cloud.
## Node Network details are not needed when in nodeport mode / static routes are disabled / non vcenter clouds.
#nodeNetworkList: []
nodeNetworkList:
- networkName: "VDS01-VLAN114-Workload"
cidrs:
- 10.114.1.0/24
enableRHI: false # This is a cluster wide setting for BGP peering.
nsxtT1LR: '' # T1 Logical Segment mapping for backend network. Only applies to NSX-T cloud.
bgpPeerLabels: [] # Select BGP peers using bgpPeerLabels, for selective VsVip advertisement.
# bgpPeerLabels:
# - peer1
# - peer2
#vipNetworkList: [] # Network information of the VIP network. Multiple networks allowed only for AWS Cloud.
vipNetworkList:
- networkName: "VDS01-VLAN112-VIP"
cidr: 10.112.1.0/24
### This section outlines all the knobs used to control Layer 7 loadbalancing settings in AKO.
L7Settings:
defaultIngController: 'true'
noPGForSNI: false # Switching this knob to true, will get rid of poolgroups from SNI VSes. Do not use this flag, if you don't want http caching. This will be deprecated once the controller support caching on PGs.
serviceType: NodePortLocal # enum NodePort|ClusterIP|NodePortLocal
shardVSSize: LARGE # Use this to control the layer 7 VS numbers. This applies to both secure/insecure VSes but does not apply for passthrough. ENUMs: LARGE, MEDIUM, SMALL, DEDICATED
passthroughShardSize: SMALL # Control the passthrough virtualservice numbers using this ENUM. ENUMs: LARGE, MEDIUM, SMALL
### This section outlines all the knobs used to control Layer 4 loadbalancing settings in AKO.
L4Settings:
advancedL4: 'false' # Use this knob to control the settings for the services API usage. Default to not using services APIs: https://github.com/kubernetes-sigs/service-apis
defaultDomain: '' # If multiple sub-domains are configured in the cloud, use this knob to set the default sub-domain to use for L4 VSes.
autoFQDN: default # ENUM: default(<svc>.<ns>.<subdomain>), flat (<svc>-<ns>.<subdomain>), "disabled" If the value is disabled then the FQDN generation is disabled.
### This section outlines settings on the Avi controller that affects AKO's functionality.
ControllerSettings:
serviceEngineGroupName: seg-tkgm-guest1 # Name of the ServiceEngine Group.
controllerVersion: 20.1.6 # The controller API version
cloudName: Default-Cloud # The configured cloud name on the Avi controller.
controllerHost: '10.115.1.52' # IP address or Hostname of Avi Controller
tenantsPerCluster: 'false' # If set to true, AKO will map each kubernetes cluster uniquely to a tenant in Avi
tenantName: admin # Name of the tenant where all the AKO objects will be created in AVI. // Required only if tenantsPerCluster is set to True
nodePortSelector: # Only applicable if serviceType is NodePort
key: ''
value: ''
resources:
limits:
cpu: 250m
memory: 300Mi
requests:
cpu: 100m
memory: 200Mi
podSecurityContext: {}
rbac:
# Creates the pod security policy if set to true
pspEnable: false
avicredentials:
username: 'admin'
password: 'VMware1!'
certificateAuthorityData:
persistentVolumeClaim: ''
mountPath: /log
logFile: avi.log
values.yaml for TKG-m Cluster 2 AKO Install. Things to note are the cniPlugin: antrea and the serviceEngineGroupName which is the same as SE group that I define for TKG-m Cluster 1.
# Default values for ako.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: projects.registry.vmware.com/ako/ako
pullPolicy: IfNotPresent
### This section outlines the generic AKO settings
AKOSettings:
logLevel: WARN # enum: INFO|DEBUG|WARN|ERROR
fullSyncFrequency: '1800' # This frequency controls how often AKO polls the Avi controller to update itself with cloud configurations.
apiServerPort: 8080 # Internal port for AKO's API server for the liveness probe of the AKO pod default=8080
deleteConfig: 'false' # Has to be set to true in configmap if user wants to delete AKO created objects from AVI
disableStaticRouteSync: 'false' # If the POD networks are reachable from the Avi SE, set this knob to true.
clusterName: tkgm-guest2 # A unique identifier for the kubernetes cluster, that helps distinguish the objects for this cluster in the avi controller. // MUST-EDIT
cniPlugin: 'antrea' # Set the string if your CNI is calico or openshift. enum: calico|canal|flannel|openshift|antrea|ncp
enableEVH: false # This enables the Enhanced Virtual Hosting Model in Avi Controller for the Virtual Services
layer7Only: false # If this flag is switched on, then AKO will only do layer 7 loadbalancing.
# NamespaceSelector contains label key and value used for namespacemigration
# Same label has to be present on namespace/s which needs migration/sync to AKO
namespaceSelector:
labelKey: ''
labelValue: ''
servicesAPI: false # Flag that enables AKO in services API mode: https://kubernetes-sigs.github.io/service-apis/. Currently implemented only for L4. This flag uses the upstream GA APIs which are not backward compatible
# with the advancedL4 APIs which uses a fork and a version of v1alpha1pre1
### This section outlines the network settings for virtualservices.
NetworkSettings:
## This list of network and cidrs are used in pool placement network for vcenter cloud.
## Node Network details are not needed when in nodeport mode / static routes are disabled / non vcenter clouds.
#nodeNetworkList: []
nodeNetworkList:
- networkName: "VDS01-VLAN114-Workload"
cidrs:
- 10.114.1.0/24
enableRHI: false # This is a cluster wide setting for BGP peering.
nsxtT1LR: '' # T1 Logical Segment mapping for backend network. Only applies to NSX-T cloud.
bgpPeerLabels: [] # Select BGP peers using bgpPeerLabels, for selective VsVip advertisement.
# bgpPeerLabels:
# - peer1
# - peer2
#vipNetworkList: [] # Network information of the VIP network. Multiple networks allowed only for AWS Cloud.
vipNetworkList:
- networkName: "VDS01-VLAN112-VIP"
cidr: 10.112.1.0/24
### This section outlines all the knobs used to control Layer 7 loadbalancing settings in AKO.
L7Settings:
defaultIngController: 'true'
noPGForSNI: false # Switching this knob to true, will get rid of poolgroups from SNI VSes. Do not use this flag, if you don't want http caching. This will be deprecated once the controller support caching on PGs.
serviceType: NodePortLocal # enum NodePort|ClusterIP|NodePortLocal
shardVSSize: LARGE # Use this to control the layer 7 VS numbers. This applies to both secure/insecure VSes but does not apply for passthrough. ENUMs: LARGE, MEDIUM, SMALL, DEDICATED
passthroughShardSize: SMALL # Control the passthrough virtualservice numbers using this ENUM. ENUMs: LARGE, MEDIUM, SMALL
### This section outlines all the knobs used to control Layer 4 loadbalancing settings in AKO.
L4Settings:
advancedL4: 'false' # Use this knob to control the settings for the services API usage. Default to not using services APIs: https://github.com/kubernetes-sigs/service-apis
defaultDomain: '' # If multiple sub-domains are configured in the cloud, use this knob to set the default sub-domain to use for L4 VSes.
autoFQDN: default # ENUM: default(<svc>.<ns>.<subdomain>), flat (<svc>-<ns>.<subdomain>), "disabled" If the value is disabled then the FQDN generation is disabled.
### This section outlines settings on the Avi controller that affects AKO's functionality.
ControllerSettings:
serviceEngineGroupName: seg-tkgm-guest1 # Name of the ServiceEngine Group.
controllerVersion: 20.1.6 # The controller API version
cloudName: Default-Cloud # The configured cloud name on the Avi controller.
controllerHost: '10.115.1.52' # IP address or Hostname of Avi Controller
tenantsPerCluster: 'false' # If set to true, AKO will map each kubernetes cluster uniquely to a tenant in Avi
tenantName: admin # Name of the tenant where all the AKO objects will be created in AVI. // Required only if tenantsPerCluster is set to True
nodePortSelector: # Only applicable if serviceType is NodePort
key: ''
value: ''
resources:
limits:
cpu: 250m
memory: 300Mi
requests:
cpu: 100m
memory: 200Mi
podSecurityContext: {}
rbac:
# Creates the pod security policy if set to true
pspEnable: false
avicredentials:
username: 'admin'
password: 'VMware1!'
certificateAuthorityData:
persistentVolumeClaim: ''
mountPath: /log
logFile: avi.log
Conclusion
With Antrea NodePortLocal(NPL) and AKO leveraging NPL, we can the option of sharing a single AVI SE Group for multiple TKG clusters. This helps to save the number of resources required, licensing and simplify manageability on groups of AVI SE especially where you can quickly and easily deploy multiple TKG clusters with ClusterAPI.