In this article, we will see how Thunder Kubernetes Connector (TKC) can dynamically configure the Thunder ADC for load-balancing traffic to a Kubernetes cluster.
Setup
- The K8s cluster consists of:
Master: 172.16.1.12 - Node: 172.16.1.13
- Node: 172.16.1.14
The Pod network is 192.168.0.0/16.
The K8s version is:
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.2", GitCommit:"092fbfbf53427de67cac1e9fa54aaa09a28371d7", GitTreeState:"clean", BuildDate:"2021-06-16T12:59:11Z", GoVersion:"go1.16.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.2", GitCommit:"092fbfbf53427de67cac1e9fa54aaa09a28371d7", GitTreeState:"clean", BuildDate:"2021-06-16T12:53:14Z", GoVersion:"go1.16.5", Compiler:"gc", Platform:"linux/amd64"}
The Thunder ADC is running ACOS 5.2.1-p2 and has the interface ethernet 1 connected to the network 172.16.1.0/24:
interface ethernet 1
enable
ip address 172.16.1.10 255.255.255.0
Configuration
The Thunder Kubernetes Connector (TKC) will run as a Pod within the K8s cluster and will communicate with Thunder ADC on interface ethernet 1, and hence enable management access on that interface of the Thunder ADC:
enable-management service https
ethernet 1
In the K8s cluster, deploy a web service named web01, with Service type as NodePort:
$ cat a10-web01.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: webmap01
data:
index.html: "<html><h1>This is web service web01</h1><html>"
---
apiVersion: v1
kind: Service
metadata:
name: web01
spec:
type: NodePort
ports:
- name: http-port
protocol: TCP
port: 8080
targetPort: 80
selector:
app: web01
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web01
spec:
replicas: 3
selector:
matchLabels:
app: web01
template:
metadata:
labels:
app: web01
spec:
volumes:
- name: volmap
configMap:
name: webmap01
containers:
- name: nginx
image: nginx:1.13
ports:
- containerPort: 80
volumeMounts:
- name: volmap
mountPath: /usr/share/nginx/html/
$ kubectl apply -f a10-web01.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
web01-68c59f6f4c-6cqzb 1/1 Running 0 5d18h
web01-68c59f6f4c-722wm 1/1 Running 0 5d18h
web01-68c59f6f4c-qgmv5 1/1 Running 0 42d
Next, we will create a Secret object with base64 encoding of the default username/password for the Thunder ADC (admin/a10):
$ cat a10-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: a10-secret
type: Opaque
data:
username: YWRtaW4=
password: YTEw
$ kubectl apply -f a10-secret.yaml
Deploy ServiceAccount, ClusterRole, and ClusterRoleBinding objects.
This ServiceAccount will subsequently be applied to the TKC, thereby granting the TKC the required permissions to access the various resources within the K8s cluster.
$ cat a10-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: a10-ingress
namespace: default
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: a10-ingress
rules:
- apiGroups: [""]
resources: ["pods", "nodes", "services", "endpoints", "secrets", "configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: ["extensions", "networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "watch"]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: a10-ingress
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: a10-ingress
subjects:
- kind: ServiceAccount
name: a10-ingress
namespace: default
$ kubectl apply -f a10-rbac.yaml
Now deploy an Ingress Resource with ingress class of a10-ext:
$ cat a10-ingress01.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: a10-ingress01
namespace: default
annotations:
kubernetes.io/ingress.class: a10-ext
acos.a10networks.com/health-monitors: '[{"name":"ws-mon-web01", "port":"80","type":"http"}]'
web01.acos.a10networks.com/service-group: '{"name":"ws-sg-web01","protocol":"tcp","monitor":"ws-mon-web01","disableMonitor":false}'
acos.a10networks.com/virtual-server: '{"name":"ws-vip-web01","vip":"172.16.1.251"}'
acos.a10networks.com/virtual-ports: '[{"port":"80","protocol":"http","http2":false,"snat":true}]'
spec:
rules:
- host: web01.a10tests.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web01
port:
number: 8080
$ kubectl apply -f a10-ingress01.yaml
$ kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
a10-ingress01 web01.a10tests.com 80 4d2h
Note that “web01” in:
web01.acos.a10networks.com/service-group: '{"name":"ws-sg-web01","protocol":"tcp","monitor":"ws-mon-web01","disableMonitor":false}'
should match the name of the web service deployed earlier.
To deploy the TKC, create the following file:
$ cat a10-tkc-v1.10.3.0.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: a10-thunder-kubernetes-connector
spec:
replicas: 1
selector:
matchLabels:
app: thunder-kubernetes-connector
template:
metadata:
labels:
app: thunder-kubernetes-connector
spec:
serviceAccountName: a10-ingress
containers:
- name: thunder-kubernetes-connector
image: a10networks/a10-kubernetes-connector:1.10.3.0
imagePullPolicy: IfNotPresent
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: WATCH_NAMESPACE
value: default
- name: CONTROLLER_URL
value: https://172.16.1.10
- name: ACOS_USERNAME_PASSWORD_SECRETNAME
value: a10-secret
- name: PARTITION
value: shared
args:
- --watch-namespace=$(WATCH_NAMESPACE)
- --use-node-external-ip=true
- --patch-to-update=true
- --safe-acos-delete=true
- --use-ingress-class-only=true
- --ingress-class=a10-ext
The value of CONTROLLER_URL is specified as 172.16.1.10, which is the IP address of interface ethernet 1 on the Thunder ADC.
Deploy the TKC:
$ kubectl apply -f a10-tkc.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
a10-thunder-kubernetes-connector-797b545746-d2t6p 1/1 Running 0 113s
web01-68c59f6f4c-6cqzb 1/1 Running 0 5d18h
web01-68c59f6f4c-722wm 1/1 Running 0 5d18h
web01-68c59f6f4c-qgmv5 1/1 Running 0 42d
On the Thunder ADC, you will see the following configuration has been added by the TKC:
health monitor ws-mon-web01
method http port 32330 expect response-code 200 url GET /
!
slb server 172.16.1.13 172.16.1.13
port 32330 tcp
!
slb server 172.16.1.14 172.16.1.14
port 32330 tcp
!
slb service-group ws-sg-web01 tcp
health-check ws-mon-web01
member 172.16.1.13 32330
member 172.16.1.14 32330
!
slb virtual-server ws-vip-web01 172.16.1.251
port 80 http
source-nat auto
service-group ws-sg-web01
Verification
On the client machine we have a DNS entry for “web01.a10tests.com” mapped to the VIP on the Thunder ADC:
$ cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.1.251 web01.a10tests.com
Now you can access the website http://web01.a10tests.com from this client machine:
More Information
For more information see the webinar:
https://www.a10networks.com/webinars/advanced-application-access-for-kubernetes/