[Yandex Cloud documentation](../../index.md) > [Yandex Cloud Marketplace](../index.md) > Users > [Tutorials](index.md) > Using Cloud Marketplace products in Managed Service for Kubernetes > Creating an L7 load balancer with a Smart Web Security profile through an Application Load Balancer ingress controller

# Creating an L7 load balancer with a Smart Web Security profile through an Application Load Balancer ingress controller

With [Yandex Smart Web Security](../../smartwebsecurity/concepts/index.md), you can protect apps in a Yandex Managed Service for Kubernetes cluster against DDoS attacks and bots. To do this, publish your apps through an ingress resource associated with a Smart Web Security [profile](../../smartwebsecurity/concepts/profiles.md) that uses a [Gwin controller](../../application-load-balancer/tools/gwin/index.md) or an [Application Load Balancer ingress controller](../../application-load-balancer/tools/k8s-ingress-controller/index.md).

{% note tip %}

We recommend using the new [Yandex Cloud Gwin](../../application-load-balancer/tools/gwin/index.md) controller instead of an ALB Ingress controller and Gateway API.

{% endnote %}

Based on the ingress resource, an L7 load balancer will be deployed with a security profile associated with the load balancer’s virtual hosts. Smart Web Security will be protecting the application backends specified in the ingress resource: all HTTP requests to the backends [will be processed](../../smartwebsecurity/concepts/rules.md#rule-action) according to the security profile rules.

To create an L7 load balancer with an associated security profile using ingress:

1. [Install a load balancer controller](#deploy-controller).
1. [Create a test application](#deploy-app).
1. [Create a security profile](#create-security-profile).
1. [Create an ingress resource](#deploy-ingress).
1. [Create a DNS record for the domain](#create-dns-record).
1. [Check the result](#check-the-result).

If you no longer need the resources you created, [delete them](#clear-out).


## Required paid resources {#paid-resources}

The support cost for this solution includes:

* Fee for a DNS zone and DNS requests (see [Cloud DNS pricing](../../dns/pricing.md)).
* Fee for using the master and outgoing traffic in a Managed Service for Kubernetes cluster (see [Managed Service for Kubernetes pricing](../../managed-kubernetes/pricing.md)).
* Fee for using computing resources, OS, and storage in cluster nodes (VMs) (see [Compute Cloud pricing](../../compute/pricing.md)).
* Fee for using L7 load balancer's computing resources (see [Application Load Balancer pricing](../../application-load-balancer/pricing.md)).
* Fee for public IP addresses for cluster nodes and L7 load balancer (see [Virtual Private Cloud pricing](../../vpc/pricing.md#prices-public-ip)).
* Fee for the number of requests to Smart Web Security (see [Smart Web Security pricing](../../smartwebsecurity/pricing.md)).


## Getting started {#before-you-begin}

1. Set up the required infrastructure:

    {% list tabs group=instructions %}

    - Manually {#manual}

        1. [Create a service account](../../iam/operations/sa/create.md) for the Application Load Balancer ingress controller to use.

            Assign the following [roles](../../application-load-balancer/operations/k8s-ingress-controller-install.md#before-you-begin) to the account for the folder to create the cluster in:

            * [alb.editor](../../application-load-balancer/security/index.md#alb-editor)
            * [vpc.publicAdmin](../../vpc/security/index.md#vpc-public-admin)
            * [compute.viewer](../../compute/security/index.md#compute-viewer)
            * [smart-web-security.editor](../../smartwebsecurity/security/index.md#smart-web-security-editor)
            * [k8s.viewer](../../managed-kubernetes/security/index.md#k8s-viewer)
            * [certificate-manager.editor](../../certificate-manager/security/index.md#certificate-manager-editor)

                {% note warning %}

                You will need this role to correctly integrate the L7 Application Load Balancer with the security profile.

                {% endnote %}

        1. Create a service account for the cluster and node group to use.

            Assign the following [roles](../../managed-kubernetes/security/index.md#sa-annotation) to the account for the folder to create the cluster in:
            * [k8s.clusters.agent](../../managed-kubernetes/security/index.md#k8s-clusters-agent)
            * [vpc.publicAdmin](../../vpc/security/index.md#vpc-public-admin)

        1. [Create security groups](../../managed-kubernetes/operations/connect/security-groups.md) for the Managed Service for Kubernetes cluster and its node groups.

            [Configure](../../application-load-balancer/tools/k8s-ingress-controller/security-groups.md) the security groups required for Application Load Balancer as well.

            {% note warning %}
            
            The configuration of security groups determines performance and availability of the cluster and the services and applications running in it.
            
            {% endnote %}

        1. [Create a cluster](../../managed-kubernetes/operations/kubernetes-cluster/kubernetes-cluster-create.md). When creating a cluster, select:

            * Service account you created earlier to use for resources and nodes.
            * Security groups you created earlier to assign to the cluster.
            * Option for assigning a public address to the cluster. This address enables using the Kubernetes API from the internet.

        1. [Create a node group](../../managed-kubernetes/operations/node-group/node-group-create.md) in the cluster. When creating the node group, select:

            * Security groups you created earlier to assign to the node group.
            * Option for assigning a public address to the nodes. This address enables downloading images from the internet.

    - Terraform {#tf}

        1. If you do not have Terraform yet, [install it](../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform).
        1. [Get the authentication credentials](../../tutorials/infrastructure-management/terraform-quickstart.md#get-credentials). You can add them to environment variables or specify them later in the provider configuration file.
        1. [Configure and initialize a provider](../../tutorials/infrastructure-management/terraform-quickstart.md#configure-provider). There is no need to create a provider configuration file manually, you can [download it](https://github.com/yandex-cloud-examples/yc-terraform-provider-settings/blob/main/provider.tf).
        1. Place the configuration file in a separate working directory and [specify the parameter values](../../tutorials/infrastructure-management/terraform-quickstart.md#configure-provider). If you did not add the authentication credentials to environment variables, specify them in the configuration file.

        1. Download the [alb-ready-k8s-cluster.tf](https://github.com/yandex-cloud-examples/yc-alb-mk8s-with-sws-profile/blob/main/alb-ready-k8s-cluster.tf) cluster configuration file to the same working directory. This file describes:
            * [Network](../../vpc/concepts/network.md#network).
            * [Subnet](../../vpc/concepts/network.md#subnet).
            * Kubernetes cluster.
            * [Service account](../../iam/concepts/users/service-accounts.md) required for the Managed Service for Kubernetes cluster and node group.
            * Service account required for the Application Load Balancer ingress controller.
            * [Security groups](../../vpc/concepts/security-groups.md) which contain [rules](../../managed-kubernetes/operations/connect/security-groups.md) required for the Managed Service for Kubernetes cluster and its node groups.

                [Some rules](../../application-load-balancer/tools/k8s-ingress-controller/security-groups.md) are required for Application Load Balancer to work correctly.

                {% note warning %}
                
                The configuration of security groups determines performance and availability of the cluster and the services and applications running in it.
                
                {% endnote %}
                
            * [Security profile](../../smartwebsecurity/concepts/profiles.md) in Smart Web Security with a [smart protection rule](../../smartwebsecurity/concepts/rules.md#smart-protection-rules) and a simple rule to [test](#check-the-result) the profile; this rule will only allow traffic from a specific IP address.
              
              The default [basic rule](../../smartwebsecurity/concepts/rules.md#base-rules) is not specified in the manifest and is created automatically.

        1. Specify the following in the configuration file:

            * [Folder ID](../../resource-manager/operations/folder/get-id.md).
            * Kubernetes version for the Kubernetes cluster and node groups.
            * Kubernetes cluster CIDR; CIDR of the services.
            * Name of the Managed Service for Kubernetes cluster service account.
            * Application Load Balancer service account name.
            * Smart Web Security profile name.
            * IP address to allow traffic from.

        1. Make sure the Terraform configuration files are correct using this command:

            ```bash
            terraform validate
            ```

            Terraform will display any configuration errors detected in your files.

        1. Create the required infrastructure:

            1. Run this command to view the planned changes:
            
               ```bash
               terraform plan
               ```
            
               If you described the configuration correctly, the terminal will display a list of the resources to update and their parameters. This is a verification step that does not apply changes to your resources.
            
            1. If everything looks correct, apply the changes:
               1. Run this command:
            
                  ```bash
                  terraform apply
                  ```
            
               1. Confirm updating the resources.
               1. Wait for the operation to complete.

            All the required resources will be created in the specified folder. You can check resource availability and their settings in the [management console](https://console.yandex.cloud).
            
        {% note info %}

        If you deployed the infrastructure with Terraform, skip the [Creating a security profile](#create-security-profile) step.

        {% endnote %}

    {% endlist %}

1. Make sure you have a domain and can manage resource records in the DNS zone for that domain. Your test app will be available through ingress on this domain’s subdomain.

    If you do not have a domain yet, register one with any domain name registrar. To manage your domain’s resource records with Yandex Cloud DNS, [create a public DNS zone and delegate the domain](../../dns/operations/zone-create-public.md).

    {% note info %}

    In this tutorial, we will use `example.com` as a domain and `demo.example.com` as its subdomain.

    Use your own domains as you go through this tutorial.

    {% endnote %}

1. [Install kubect](https://kubernetes.io/docs/tasks/tools/install-kubectl) and [configure it to work with the new cluster](../../managed-kubernetes/operations/connect/index.md#kubectl-connect).

## Installing a load balancer controller {#deploy-controller}

{% list tabs group=alb_controller %}

- Gwin {#gwin}

  1. [Install a Gwin controller](../../application-load-balancer/tools/gwin/quickstart.md) to the `gwin-space` namespace.

      Specify the service account [you created earlier for the controller](#before-you-begin).

      By uing the separate `gwin-space` namespace, you isolate the controller resources from those of your [test application](#deploy-app) and [ingress](#deploy-ingress).

  1. Make sure you successfully installed the controller:

      ```bash
      kubectl logs deployment.apps/gwin -n gwin-space
      ```

      Logs should contain messages saying the Gwin controller successfully started.

      {% cut "Example of a command result part" %}

      ```text
      level=INFO source=/yc_gwin/cmd/gwin/app/serve.go:467 msg="Server setup completed successfully"
      level=INFO source=/yc_gwin/cmd/gwin/app/serve.go:488 msg="Starting ALB observer"
      level=INFO source=/yc_gwin/cmd/gwin/app/serve.go:490 msg="ALB observer started successfully"
      level=INFO source=/yc_gwin/cmd/gwin/app/serve.go:492 msg="Starting address updater"
      level=INFO source=/yc_gwin/cmd/gwin/app/serve.go:494 msg="Address updater started successfully"
      level=INFO source=/yc_gwin/cmd/gwin/app/serve.go:496 msg="All services configured successfully, starting controller manager"
      ```

      {% endcut %}

- Ingress controller {#alb-ingress}

  1. [Install the Application Load Balancer ingress controller](../../application-load-balancer/operations/k8s-ingress-controller-install.md) to the `yc-alb` namespace.

      Specify the service account [you created earlier for the controller](#before-you-begin).

      By uing the separate `yc-alb` namespace, you isolate the controller resources from those of your [test application](#deploy-app) and [ingress](#deploy-ingress).

  1. Make sure you successfully installed the controller:

      ```bash
      kubectl logs deployment.apps/yc-alb-ingress-controller -n yc-alb
      ```

      Logs should contain messages saying the ingress controller successfully started.

      {% cut "Example of a command result part" %}

      ```text
      ...    INFO    Starting EventSource    {"controller": "ingressgroup", ...}
      ...    INFO    Starting Controller     {"controller": "ingressgroup"}
      ...    INFO    Starting EventSource    {"controller": "grpcbackendgroup", "controllerGroup": "alb.yc.io", ...}
      ...    INFO    Starting Controller     {"controller": "grpcbackendgroup", "controllerGroup": "alb.yc.io", ...}
      ...    INFO    Starting EventSource    {"controller": "httpbackendgroup", "controllerGroup": "alb.yc.io", ...}
      ...    INFO    Starting Controller     {"controller": "httpbackendgroup", "controllerGroup": "alb.yc.io", ...}

      ...

      ...    INFO    Starting workers        {"controller": "ingressgroup", ...}
      ...    INFO    Starting workers        {"controller": "grpcbackendgroup", "controllerGroup": "alb.yc.io", ...}
      ...    INFO    Starting workers        {"controller": "httpbackendgroup", "controllerGroup": "alb.yc.io", ...}
      ```

      {% endcut %}

{% endlist %}

## Create a test application {#deploy-app}

Create an application and an associated service for ingress to expose:

1. Create a manifest named `demo-app1.yaml` for deploying your application:

    {% cut "`demo-app1.yaml`" %}

    ```yaml
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: demo-app1
      labels:
        tutorial: sws
    data:
      nginx.conf: |
        worker_processes auto;
        events {
        }
        http {
          server {
            listen 80 ;
            location = /_healthz {
              add_header Content-Type text/plain;
              return 200 'ok';
            }
            location / {
              add_header Content-Type text/plain;
              return 200 'Index';
            }
            location = /app1 {
              add_header Content-Type text/plain;
              return 200 'This is APP#1';
            }
          }
        }
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: demo-app1
      labels:
        app: demo-app1
        tutorial: sws
        version: v1
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: demo-app1
      strategy:
        type: RollingUpdate
        rollingUpdate:
          maxSurge: 1
          maxUnavailable: 0
      template:
        metadata:
          labels:
            app: demo-app1
            version: v1
        spec:
          terminationGracePeriodSeconds: 5
          volumes:
            - name: demo-app1
              configMap:
                name: demo-app1
          containers:
            - name: demo-app1
              image: nginx:latest
              ports:
                - name: http
                  containerPort: 80
              livenessProbe:
                httpGet:
                  path: /_healthz
                  port: 80
                initialDelaySeconds: 3
                timeoutSeconds: 2
                failureThreshold: 2
              volumeMounts:
                - name: demo-app1
                  mountPath: /etc/nginx
                  readOnly: true
              resources:
                limits:
                  cpu: 250m
                  memory: 128Mi
                requests:
                  cpu: 100m
                  memory: 64Mi
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: demo-app1
      labels:
        tutorial: sws
    spec:
      selector:
        app: demo-app1
      type: NodePort
      ports:
        - name: http
          port: 80
          targetPort: 80
          protocol: TCP
    ```

    {% endcut %}

1. Deploy the application:

    ```bash
    kubectl apply -f demo-app1.yaml
    ```

    This will create the `ConfigMap`, `Deployment`, and `Service` objects for the `demo-app1` app.

1. Make sure all objects were successfully created:

    ```bash
    kubectl get configmap,deployment,svc -l tutorial=sws
    ```

    {% cut "Example of a command result" %}

    ```text
    NAME                  DATA   AGE
    configmap/demo-app1   1      ...

    NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/demo-app1   2/2     2            2           ...

    NAME                TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)      AGE
    service/demo-app1   NodePort   ...          <none>        80:.../TCP   ...
    ```

    {% endcut %}

## Create a security profile {#create-security-profile}

{% list tabs group=instructions %}

- Management console {#console}

  Create a security profile with a simple rule so you can easily [test](#check-the-result) the profile. The rules in the profile will only allow traffic from a specific IP address.

  Create a security profile:

  1. In the [management console](https://console.yandex.cloud), select the folder where you want to create a profile.
  1. Navigate to **Smart Web Security**.
  1. In the left-hand panel, select ![shield-check](../../_assets/console-icons/shield-check.svg) **Security profiles**.
  1. Click **Create profile** and select **From a preset template**.

      The profile will contain a number of preconfigured security rules:

      * [Smart protection rule](../../smartwebsecurity/concepts/rules.md#smart-protection-rules) providing full protection for all traffic. This rule takes priority over the default basic rule.
      * Default [basic rule](../../smartwebsecurity/concepts/rules.md#base-rules) denying all traffic that does not satisfy higher-priority rules.

          {% note tip %}
          
          Creating a pre-configured profile with full Smart Protection is preferable. This will ensure the highest level of security for your resource.
          
          {% endnote %}

  1. Set up the profile:

      * **Name**: Profile name, e.g., `test-sp1`.
      * **Action for the default base rule**: Action for the basic rule to effect.

          Leave `Deny` for the basic rule to deny all traffic.

  1. Add a security rule:

      1. Click ![plus-sign](../../_assets/console-icons/plus.svg) **Add rule**.

      1. Specify the main rule settings:

          * **Name**: Name for the rule, e.g., `test-rule1`.

          * **Priority**: Specify a value to give the rule priority over the preconfigured rules, e.g., `999800`.

              {% note info %}
              
              The smaller the value, the higher is the rule priority. The priorities for preconfigured rules are as follows:
              * Basic default rule: `1000000`.
              * Smart Protection rule providing full protection: `999900`.
              
              {% endnote %}

          * **Rule type**: Select `Base`.

          * **Action**: Select `Allow`.

      1. Under **Conditions**, configure the conditions to only allow traffic from a specific IP address:

          1. Select the traffic scope for the rule: `On condition`.
          1. Select the `IP` condition.
          1. For IP, select the condition: `Matches or falls within the range`.
          1. Specify a public IP address, e.g., `203.0.113.200`.

      1. Click **Add**.

      The new rule will appear in the list of security rules.

  1. Click **Create**.

  The new profile will appear in the list of security profiles. Write down the ID of your new security profile, as you will need it later.

- Terraform {#tf}

  If you have used the [alb-ready-k8s-cluster.tf](https://github.com/yandex-cloud-examples/yc-alb-mk8s-with-sws-profile/blob/main/alb-ready-k8s-cluster.tf) configuration file, the security profile [has already been created](#before-you-begin) and no further action is required.

{% endlist %}

## Create an ingress resource {#deploy-ingress}

This ingress resource will describe the Application Load Balancer properties. The load balancer controller [you installed earlier](#deploy-controller) will deploy the load balancer with the specified properties after the ingress resource is created.

As per the ingress rules, traffic to the `demo.example.com` virtual host at the `/app1` path will be routed to the [service/demo-app1](#deploy-app) backend. The [security profile you created earlier](#create-security-profile) will protect this backend.

To create an ingress resource:

1. Create a file named `demo-ingress.yaml` with the ingress resource description:

    {% list tabs group=alb_controller %}

    - Gwin {#gwin}

      ```yaml
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: demo-ingress
        annotations:
          gwin.yandex.cloud/subnets: "<list_of_subnet_IDs>"
          gwin.yandex.cloud/securityGroups: "<security_group_ID>"
          gwin.yandex.cloud/externalIPv4Address: "auto"
          gwin.yandex.cloud/groupName: "demo-sws"
          gwin.yandex.cloud/hosts.securityProfileID: "<security_profile_ID>"
      spec:
        ingressClassName: gwin-default
        rules:
          - host: demo.example.com
            http:
              paths:
                - path: /app1
                  pathType: Exact
                  backend:
                    service:
                      name: demo-app1
                      port:
                        number: 80
      ```

      Where:

      * [gwin.yandex.cloud/subnets](../../application-load-balancer/gwin-ref/ingress.md#load-balancer-configuration): List of IDs for subnets where the load balancer will reside.

          If you [created the infrastructure using Terraform](#before-you-begin), use the ID of the subnet named `subnet-a`.

      * [gwin.yandex.cloud/security-groups](../../application-load-balancer/gwin-ref/ingress.md#load-balancer-configuration): ID of the group [you created](#before-you-begin) for the load balancer.

          If you created the infrastructure with Terraform, specify the ID of the group named `alb-traffic`.

      * [gwin.yandex.cloud/hosts.securityProfileID](../../application-load-balancer/gwin-ref/ingress.md#security-configuration): ID of the security profile [you created](#create-security-profile) in Smart Web Security.

          {% note info %}

          The security profile will only apply to the virtual hosts of the ingress resource with a configured annotation. For the above ingress resource described above, the profile will apply to a single virtual host, `demo.example.com`.

          This is the only ingress resource in the `demo-sws` ingress group. The security profile will not apply to the virtual hosts of other ingress resources if you add such resources to the group later.

          {% endnote %}

      Learn more about annotations in [Ingress resource fields and annotations](../../application-load-balancer/gwin-ref/ingress.md).

    - Ingress controller {#alb-ingress}

      ```yaml
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: demo-ingress
        annotations:
          ingress.alb.yc.io/subnets: "<list_of_subnet_IDs>"
          ingress.alb.yc.io/security-groups: "<security_group_ID>"
          ingress.alb.yc.io/external-ipv4-address: "auto"
          ingress.alb.yc.io/group-name: "demo-sws"
          ingress.alb.yc.io/security-profile-id: "<security_profile_ID>"
      spec:
        rules:
          - host: demo.example.com
            http:
              paths:
                - path: /app1
                  pathType: Exact
                  backend:
                    service:
                      name: demo-app1
                      port:
                        number: 80
      ```

      Where:

      * [ingress.alb.yc.io/subnets](../../application-load-balancer/k8s-ref/ingress.md#annot-subnets): List of IDs for subnets where the load balancer will reside.

          If you [created the infrastructure using Terraform](#before-you-begin), use the ID of the subnet named `subnet-a`.

      * [ingress.alb.yc.io/security-groups](../../application-load-balancer/k8s-ref/ingress.md#annot-security-groups): ID of the group [you created](#before-you-begin) for the load balancer.

          If you created the infrastructure with Terraform, specify the ID of the group named `alb-traffic`.

      * [ingress.alb.yc.io/security-profile-id](../../application-load-balancer/k8s-ref/ingress.md#annot-security-profile-id): ID of the security profile [you created ealier](#create-security-profile) in Smart Web Security.

          {% note info %}

          The security profile will only apply to the [virtual hosts](../../application-load-balancer/tools/k8s-ingress-controller/principles.md#mapping) of the ingress resource with a configured annotation. For the above ingress resource described above, the profile will apply to a single virtual host, `demo.example.com`.

          This is the only ingress resource in the `demo-sws` ingress group. The security profile will not apply to the virtual hosts of other ingress resources if you add such resources to the group later.

      {% endnote %}

      Learn more about annotations in [Ingress resource fields and annotations](../../application-load-balancer/k8s-ref/ingress.md).

    {% endlist %}

1. Create an ingress resource:

    ```bash
    kubectl apply -f demo-ingress.yaml
    ```

    The Application Load Balancer ingress controller will start creating target groups, backend groups, HTTP routers, and the load balancer.

1. Remember to regularly check the ingress resource status until the `ADDRESS` column displays the load balancer’s IP address:

    ```bash
    kubectl get ingress demo-ingress
    ```

    This means the load balancer has been successfully created and can accept traffic.

    {% cut "Example of a command result" %}

    ```bash
    NAME             CLASS    HOSTS              ADDRESS         PORTS   AGE
    demo-ingress     <none>   demo.example.com   158.1*.*.*      80      ...
    ```

    {% endcut %}

### Create a DNS record for the domain {#create-dns-record}.

1. [Create](../../dns/operations/resource-record-create.md) an `A` record for the `demo.example.com` domain in the `example.com` zone. In its value, specify the IP address of the load balancer you created earlier.

1. Wait until the DNS propagation is finished.

    To make sure the propagation was successful, use applicable online tools or manual requests to different DNS servers:

    ```bash
    nslookup -type=a demo.example.com <DNS_server_IP_address>
    ```

## Check the result {#check-the-result}

Requests to the application deployed in the Kubernetes cluster go through an Application Load Balancer. Protection of the virtual hosts to which those requests are routed is implemented with a security profile. The profile [configuration](#create-security-profile) only allows traffic from a specific IP address, e.g., `203.0.113.200`.

Make sure the load balancer works correctly as per the security profile settings:

1. Use a host with an allowed IP address (`203.0.113.200`) to make sure traffic is routed as per the rule defined in the ingress resource:

    ```bash
    curl http://demo.example.com/app1
    ```

    Expected result:

    ```text
    This is demo-app1
    ```

1. Use a host with an IP address not on the list of allowed ones (e.g., `203.0.113.100`) to make sure traffic is not routed:

    ```bash
    curl http://demo.example.com/app1
    ```

    The load balancer should return the [HTTP 403 Forbidden](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403) code and a message saying access to the resource is restricted.

If traffic routing does not work as expected, make sure everything is configured correctly:

* The service account for the ingress controller [must have the required roles](#before-you-begin) including those for using Smart Web Security.
* Make sure the security groups for the Managed Service for Kubernetes cluster and its node groups [are configured correctly](../../managed-kubernetes/operations/connect/security-groups.md). If a rule is missing, [add it](../../vpc/operations/security-group-add-rule.md).
* The security profile [must be configured correctly](#create-security-profile) to allow traffic from the relevant address.

{% note tip %}

After confirming the profile works properly, add more rules if required.

{% endnote %}

## Delete the resources you created {#clear-out}

Some resources are not free of charge. Delete the resources you no longer need to avoid paying for them:

1. Delete the ingress resource you created:

    ```bash
    kubectl delete ingress demo-ingress
    ```

    This will delete the load balancer and the associated HTTP router.

    The Smart Web Security profile will be disassociated from the virtual hosts specified in the ingress resource.

1. Delete the Managed Service for Kubernetes cluster and its associated infrastructure:

    {% list tabs group=instructions %}

    - Manually {#manual}

        [Delete the Managed Service for Kubernetes cluster](../../managed-kubernetes/operations/kubernetes-cluster/kubernetes-cluster-delete.md).

        If needed, delete the service account and security groups [you created before getting started](#before-you-begin).

    - Terraform {#tf}

        1. In the terminal window, go to the directory containing the infrastructure plan.
        
            {% note warning %}
        
            Make sure the directory has no Terraform manifests with the resources you want to keep. Terraform deletes all resources that were created using the manifests in the current directory.
        
            {% endnote %}
        
        1. Delete resources:
        
            1. Run this command:
        
                ```bash
                terraform destroy
                ```
        
            1. Confirm deleting the resources and wait for the operation to complete.
        
            All the resources described in the Terraform manifests will be deleted.

    {% endlist %}