Kubernetes Deployment Based on Helm Charts¶
Prerequisites¶
-
Local or cloud (EKS, GKE, AKE, etc) cluster running any version of Kubernetes
-
Application packaged as a Helm chart
-
Pod exposed to the public Internet or other potential sources of malicious web and API attacks
-
Kubernetes ingress controller or external load balancer (like AWS ELB or ALB) to add the HTTP request header
X-Forwarded-For
, which contains the real public IP address of the connecting client -
Username and password of the user with the Deploy role added to your Wallarm account. To add a new user, please follow these instructions
Installation¶
-
Create Wallarm ConfigMap.
-
Update the definition of the
Deployment
object in Kubernetes. -
Update the definition of the
Service
object in Kubernetes. -
Update the Helm chart configuration file.
-
Test the Wallarm sidecar container.
If Wallarm WAF is already installed in your environment
If you install Wallarm WAF instead of already existing Wallarm WAF or need to duplicate the installation in the same environment, please keep the same WAF version as currently used or update the version of all installations to the latest.
The version of deployed Wallarm WAF image is specified in the Helm chart configuration file → wallarm.image.tag
.
- If the version
2.16
is specified, follow the current instruction. - If the version
2.14
is specified, follow the instructions for 2.14 or increase the version of the image to2.16
in all deployments and follow the current instruction. - If the version
2.12
or lower is specified, please increase the version of the image to2.16
in all deployments and follow the current instruction.
More information about WAF node versioning is available in the WAF node versioning policy.
Step 1: Creating Wallarm ConfigMap¶
Go to the Helm chart directory > the templates
folder and create a wallarm‑sidecar‑configmap.yaml
template with the following content:
apiVersion: v1
kind: ConfigMap
metadata:
name: wallarm-sidecar-nginx-conf
data:
default: |
geo $remote_addr $wallarm_mode_real {
default {{ .Values.wallarm.mode | quote }};
# IP addresses and rules for US cloud scanners
50.116.11.251 off;45.79.143.18 off;172.104.21.210 off;74.207.237.202 off;45.79.186.159 off;45.79.216.187 off;45.33.16.32 off;96.126.127.23 off;172.104.208.113 off;192.81.135.28 off;104.237.155.105 off;45.56.71.221 off;45.79.194.128 off;104.237.151.202 off;45.33.15.249 off;45.33.43.225 off;45.79.10.15 off;45.33.79.18 off;45.79.75.59 off;23.239.30.236 off;172.104.22.150 off;45.33.86.254 off;45.56.72.191 off;45.79.75.91 off;192.155.92.134 off;23.239.4.41 off;45.79.93.164 off;45.56.122.184 off;96.126.124.141 off;45.79.115.178 off;34.94.100.64 off;35.235.101.133 off;34.94.16.235 off;35.236.51.79 off;35.236.55.214 off;35.236.127.211 off;35.236.126.84 off;35.236.3.158 off;34.94.218.5 off;35.236.118.146 off;35.236.1.4 off;35.236.20.89 off;
# IP addresses and rules for European cloud scanners
139.162.148.184 off;139.162.151.155 off;139.162.159.244 off;139.162.151.10 off;139.162.159.137 off;39.162.157.131 off;139.162.144.202 off;139.162.130.66 off;139.162.158.79 off;139.162.156.102 off;85.90.246.120 off;172.104.128.215 off;139.162.174.26 off;139.162.182.20 off;139.162.190.22 off;139.162.168.17 off;139.162.167.19 off;139.162.170.84 off;139.162.191.89 off;139.162.176.169 off;139.162.184.225 off;139.162.185.243 off;172.104.143.34 off;139.162.178.148 off;139.162.186.136 off;139.162.163.61 off;139.162.171.141 off;139.162.179.214 off;139.162.187.138 off;139.162.164.41 off;139.162.172.35 off;139.162.180.37 off;139.162.188.246 off;172.104.139.18 off;172.104.152.28 off;139.162.177.83 off;172.104.240.115 off;172.105.64.135 off;139.162.153.16 off;172.104.241.162 off;139.162.167.48 off;172.104.233.100 off;172.104.157.26 off;172.105.65.182 off;172.104.138.5 off;172.104.150.243 off;139.162.190.165 off;139.162.166.202 off;139.162.174.220 off;139.162.182.156 off;139.162.190.86 off;139.162.167.51 off;139.162.175.71 off;172.104.152.54 off;172.104.151.59 off;172.104.128.67 off;172.104.152.96 off;139.162.145.238 off;172.104.128.103 off;172.104.139.37 off;139.162.184.33 off;139.162.186.129 off;172.104.154.128 off;172.104.146.90 off;172.104.128.44 off;85.90.246.49 off;139.162.146.245 off;139.162.171.208 off;172.104.252.112 off;139.162.132.87 off;139.162.162.71 off;172.104.229.59 off;172.104.152.244 off;172.104.250.27 off;139.162.130.123 off; 178.32.42.221 off;46.105.75.84 off;51.254.85.145 off;188.165.30.182 off;188.165.136.41 off;188.165.137.10 off;54.36.135.252 off;54.36.135.253 off;54.36.135.254 off;54.36.135.255 off;54.36.131.128 off;54.36.131.129 off;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name localhost;
root /usr/share/nginx/html;
index index.html index.htm;
wallarm_mode $wallarm_mode_real;
# wallarm_instance 1;
{{ if eq .Values.wallarm.enable_ip_blocking "true" }}
wallarm_acl default;
{{ end }}
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
location / {
proxy_pass http://localhost:{{ .Values.wallarm.app_container_port }};
include proxy_params;
}
}
Step 2: Updating the Deployment Object in Kubernetes¶
- Return to the Helm chart directory > the
templates
folder and open the template defining theDeployment
object for the application. A complex application can have severalDeployment
objects for different components of the application - please find an object which defines pods which are actually exposed to the Internet. For example:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
# Definition of your main app container
- name: myapp
image: <Image>
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
# Port on which the application container accepts incoming requests
- containerPort: 8080
- Copy the following elements to the template:
- the
checksum/config
annotation to thespec.template.metadata.annotations
section to update the running pods after a change in the previously created ConfigMap object, - the
wallarm
sidecar container definition to thespec.template.spec.containers
section, - the
wallarm-nginx-conf
volume definition to thespec.template.spec.volumes
section.
Wallarm element
comment. - the
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
# Wallarm element: annotation to update running pods after changing Wallarm ConfigMap
checksum/config: {{ include (print $.Template.BasePath "/wallarm-sidecar-configmap.yaml") . | sha256sum }}
name: myapp
spec:
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
# Wallarm element: definition of Wallarm sidecar container
- name: wallarm
image: {{ .Values.wallarm.image.repository }}:{{ .Values.wallarm.image.tag }}
imagePullPolicy: {{ .Values.wallarm.image.pullPolicy | quote }}
env:
- name: WALLARM_API_HOST
value: {{ .Values.wallarm.wallarm_host_api | quote }}
- name: DEPLOY_USER
value: {{ .Values.wallarm.deploy_username | quote }}
- name: DEPLOY_PASSWORD
value: {{ .Values.wallarm.deploy_password | quote }}
- name: DEPLOY_FORCE
value: "true"
- name: WALLARM_ACL_ENABLE
value: "true"
- name: TARANTOOL_MEMORY_GB
value: {{ .Values.wallarm.tarantool_memory_gb | quote }}
ports:
- name: http
# Port on which the Wallarm sidecar container accepts requests
# from the Service object
containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/sites-enabled
readOnly: true
name: wallarm-nginx-conf
# Definition of your main app container
- name: myapp
image: <Image>
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
# Port on which the application container accepts incoming requests
- containerPort: 8080
volumes:
# Wallarm element: definition of the wallarm-nginx-conf volume
- name: wallarm-nginx-conf
configMap:
name: wallarm-sidecar-nginx-conf
items:
- key: default
path: default
- Update the
ports.containerPort
value in sidecar container definition following the code comments.
Step 3: Updating the Service Object in Kubernetes¶
- Return to the Helm chart directory > the
templates
folder and open the template defining theService
object that points toDeployment
modified in the previous step. For example:
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
ports:
- port: {{ .Values.service.port }}
# Wallarm sidecar container port;
# the value must be identical to ports.containerPort
# in definition of Wallarm sidecar container
targetPort: 8080
- Change the
ports.targetPort
value to point to the Wallarm sidecar container port (ports.containerPort
defined in the Wallarm sidecar container). For example:
...
- port: {{ .Values.service.port }}
# Wallarm sidecar container port;
# the value must be identical to ports.containerPort
# in definition of Wallarm sidecar container
targetPort: 80
Step 4: Updating the Helm Chart Configuration File¶
- Return to the Helm chart directory and open the
values.yaml
file.
- Copy the
wallarm
object definition provided below tovalues.yaml
and update parameter values following the code comments.
wallarm:
image:
repository: wallarm/node
tag: 2.16
pullPolicy: Always
# Wallarm API endpoint:
# "api.wallarm.com" for the EU cloud
# "us1.api.wallarm.com" for the US cloud
wallarm_host_api: "api.wallarm.com"
# Username of the user with the Deploy role
deploy_username: "username"
# Password of the user with the Deploy role
deploy_password: "password"
# Port on which the container accepts incoming requests,
# the value must be identical to ports.containerPort
# in definition of your main app container
app_container_port: 80
# Request filtering mode:
# "off" to disable request processing
# "monitoring" to process but not block requests
# "block" to process all requests and block the malicious ones
mode: "block"
# Amount of memory in GB for request analytics data,
# recommended value is 75% of the total server memory
tarantool_memory_gb: 2
# Set to "true" to enable the WAF IP Blocking functionality
enable_ip_blocking: "false"
- Make sure the
values.yaml
file is valid using the following command:
helm lint
- Deploy the modified Helm chart in the Kubernetes cluster using the following command:
helm upgrade <RELEASE> <CHART>
-
<RELEASE>
is the name of an existing Helm chart, -
<CHART>
is the path to the Helm chart directory.
NetworkPolicy Object in Kubernetes
If the application also uses the NetworkPolicy
object it should be updated to reflect the Wallarm sidecar container port specified above.
Step 5: Testing the Wallarm Sidecar Container¶
-
Get the list of pods using the following command:
kubectl get pods
The number of containers in the pod should increase, and the status of the pod should be "Running".
NAME READY STATUS RESTARTS AGE mychart-856f957bbd-cr4kt 2/2 Running 0 3m48s
-
Go to your Wallarm account > Nodes via the link below and make sure that a new node is displayed. This created node is used to filter requests to your application.
-
Send a malicious test attack request to the application as described in these instructions.
-
Go to your Wallarm account > Events via the link below and make sure that an attack is displayed in the list: