Thunder Kubernetes Connector with Thunder ADC
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 <none> 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/