Installing the Gwin controller
Gwin is a tool for managing Yandex Application Load Balancer in Yandex Managed Service for Kubernetes clusters.
Follow this guide to install the Gwin controller in a Managed Service for Kubernetes cluster. Based on the Ingress or Gateway API resource configurations, the controller automatically deploys an Application Load Balancer that:
- Automatically gets a dynamic public IP address.
- Accepts HTTP traffic on port
80. - Accepts HTTPS traffic on port
443using a certificate in Certificate Manager. - Sends GET requests to a test service named
example-service.
Required paid resources
The infrastructure support cost includes:
- Fee for the Managed Service for Kubernetes master (see Managed Service for Kubernetes pricing).
- Fee for Managed Service for Kubernetes cluster nodes: specifically using computing resources and storage (see Compute Cloud pricing).
- Fee for public IP addresses for Managed Service for Kubernetes cluster hosts and Managed Service for Kubernetes cluster nodes with public access enabled (see Virtual Private Cloud pricing).
- Fee for using the load balancer's computing resources (see Application Load Balancer pricing).
Getting started
-
If you do not have the Yandex Cloud CLI installed yet, install and initialize it.
By default, the CLI uses the folder specified when creating the profile. To change the default folder, use the
yc config set folder-id <folder_ID>command. You can also set a different folder for any specific command using the--folder-nameor--folder-idparameter. -
Create security groups for the Managed Service for Kubernetes cluster and its node groups.
Also configure the security groups required for Application Load Balancer.
Warning
The configuration of security groups determines the performance and availability of the cluster and the services and applications running in it.
-
Create a Managed Service for Kubernetes cluster. When creating, specify the preconfigured security groups.
-
Create a node group. To enable internet access for your node group (e.g., for Docker image pulls), assign it a public IP address. Specify the preconfigured security groups.
-
Install kubect
and configure it to work with the new cluster. -
Create a service account the controller will use to create Application Load Balancer resources and assign it the following roles for the folder:
- alb.editor: To create Application Load Balancer resources.
- vpc.publicAdmin: To manage external network connectivity.
- certificate-manager.certificates.downloader: If you use cloud certificates registered with Yandex Certificate Manager.
- certificate-manager.editor: If you use Managed Service for Kubernetes cluster certificates. In this case, the controller creates the relevant cloud certificates.
- compute.viewer: To use Managed Service for Kubernetes cluster nodes in the L7 load balancer target groups.
- k8s.viewer: To enable the controller to determine the network for deploying the L7 load balancer.
- smart-web-security.editor: To connect a Yandex Smart Web Security profile to an L7 load balancer's virtual host. This role is optional.
- logging.writer: If the Gateway resource specifies a log group to write L7 load balancer logs to Yandex Cloud Logging. This role is optional.
-
Create an authorized access key for the service account in JSON format and save it to the
sa-key.jsonfile:yc iam key create \ --service-account-name <service_account_name> \ --output sa-key.json
Installing Gwin
Installation from Yandex Cloud Marketplace
-
Navigate to the folder dashboard
and select Managed Service for Kubernetes. -
Click the name of the Managed Service for Kubernetes cluster you need and select the
Marketplace tab. -
Under Application available for installation, select Gwin and click Go to install.
-
Configure the application:
- Namespace: Create a new namespace, e.g.,
gwin-space. If you leave the default namespace, Gwin may work incorrectly. - Application name: Specify the application name.
- Folder ID: Specify the ID of the folder Gwin will operate from.
- Service account key: Copy the contents of the
sa-key.jsonfile.
- Namespace: Create a new namespace, e.g.,
-
Click Install.
-
Wait for the application status to change to
Deployed.
Installation using a Helm chart
-
Install Helm
v3.8.0 or higher. -
To install a Helm chart
with the Gwin controller, run this command:helm pull oci://cr.yandex/yc-marketplace/yandex-cloud/gwin/gwin-chart \ --version v1.0.4 \ --untar \ helm install \ --namespace <namespace> \ --create-namespace \ --set controller.folderId=<folder_ID> \ --set-file controller.ycServiceAccount.secret.value=./sa-key.json \ gwin ./gwin-chartIf you set
namespaceto its default, Gwin may work incorrectly. We recommend specifying a value different from all existing namespaces, e.g.,gwin-space.You can get the folder ID with the list of folders in the cloud.
Create a test app
To test the Gwin controller, create a test application named example-app:
-
Create a custom certificate for your application's domain:
openssl req -x509 -newkey rsa:4096 -keyout example-com.key -out example-com.crt -days 365 -nodes -subj \ "/C=RU/ST=Moscow/L=Moscow/O=Example/OU=IT/CN=example.com"This command generates a self-signed certificate along with a matching private key. As a result, you will have two files:
example-com.crtwith the certificate.example-com.keywith the private key.
-
Add the certificate to Certificate Manager:
yc certificate-manager certificate create \ --folder-id <folder_ID> \ --name example-certificate \ --chain example-com.crt \ --key example-com.keyCheck the result and save the certificate ID (the
idfield):id: fpqmg47avvim******** folder_id: b1g7gvsi89m3******** created_at: "2020-09-15T06:54:44.916325Z" ... issued_at: "2020-09-15T06:54:44.916325Z" not_after: "2021-09-15T06:48:26Z" not_before: "2020-09-15T06:48:26Z" -
Create a namespace for the app:
kubectl create namespace example-ns -
In a separate directory, create a configuration file named
example-app.yamlfor your application:apiVersion: apps/v1 kind: Deployment metadata: name: example-deployment namespace: example-ns labels: app: example-app spec: replicas: 2 selector: matchLabels: app: example-app template: metadata: labels: app: example-app spec: containers: - name: nginx image: nginx:alpine ports: - containerPort: 80 volumeMounts: - name: config-volume mountPath: /etc/nginx/conf.d volumes: - name: config-volume configMap: name: example-html --- apiVersion: v1 kind: ConfigMap metadata: name: example-html namespace: example-ns data: default.conf: | server { listen 80; server_name _; location / { return 200 'Hello World'; add_header Content-Type text/plain; } } --- apiVersion: v1 kind: Service metadata: name: example-service namespace: example-ns labels: app: example-app spec: type: NodePort ports: - port: 80 targetPort: 80 nodePort: 30080 protocol: TCP name: http selector: app: example-app -
In the same directory, create a configuration file named
resources.yamlfor the Gateway API or Ingress resources:Gateway APIIngressapiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: example-gateway namespace: example-ns annotations: gwin.yandex.cloud/securityGroups: <load_balancer_security_group_IDs> spec: gatewayClassName: gwin-default listeners: - name: http protocol: HTTP port: 80 hostname: "example.com" allowedRoutes: namespaces: from: Same - name: https protocol: HTTPS port: 443 hostname: "example.com" allowedRoutes: namespaces: from: Same tls: certificateRefs: - group: gwin.yandex.cloud kind: YCCertificate name: example-certificate addresses: - type: gwin.yandex.cloud/autoIPv4 value: auto --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: example-redirect-httproute namespace: example-ns spec: hostnames: - "example.com" parentRefs: - name: example-gateway sectionName: http rules: - filters: - type: RequestRedirect requestRedirect: scheme: https statusCode: 301 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: example-httproute namespace: example-ns spec: hostnames: - "example.com" parentRefs: - name: example-gateway sectionName: https rules: - matches: - path: value: /api type: PathPrefix method: GET backendRefs: - kind: Service name: example-service port: 80 --- apiVersion: gwin.yandex.cloud/v1 kind: YCCertificate metadata: name: example-certificate namespace: example-ns spec: certificateRef: certificateID: "<certificate_ID>"apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress namespace: example-ns annotations: gwin.yandex.cloud/groupName: example gwin.yandex.cloud/externalIPv4Address: auto gwin.yandex.cloud/rules.allowedMethods: "GET" gwin.yandex.cloud/securityGroups: <load_balancer_security_group_IDs> spec: ingressClassName: gwin-default rules: - host: example.com http: paths: - pathType: Prefix path: "/api" backend: service: name: example-service port: number: 80 tls: - hosts: - example.com secretName: "yc-certmgr-cert-id-<certificate_ID>"Note
In our configuration examples, the load balancer is set up with a dynamic public IP address. Deleting the load balancer from the cloud will also delete its IP address. To avoid IP address changes in a production environment, reserve and use a static IP address.
-
Apply the configuration files:
kubectl apply -f example-app.yaml && \ kubectl apply -f resources.yaml
Check the result
-
Make sure the Application Load Balancer was created.
Gateway APIIngress-
Run this command:
kubectl get gateway -n example-ns example-gateway -
Make sure the command outputs the load balancer's IP address in the
ADDRESSfield:NAME CLASS ADDRESS PROGRAMMED AGE example-gateway gwin-default <IP_address> 32h
-
Run this command:
kubectl get ingress -n example-ns example-ingress -
Make sure the command outputs the load balancer's IP address in the
ADDRESSfield:NAME CLASS HOSTS ADDRESS PORTS AGE example-ingress gwin-default example.com <IP_address> 80, 443 31h
-
-
Make sure HTTP requests to the test application get redirected to HTTPS:
curl -I <load_balancer_IP_address> -H "Host:example.com"Expected result:
HTTP/1.1 301 Moved Permanently location: https://example.com:443/ date: Sat, 06 Sep 2025 23:09:19 GMT server: ycalb transfer-encoding: chunked -
Make sure the test application receives HTTPS requests:
curl --resolve example.com:443:<load_balancer_IP_address> \ --cacert example-com.crt \ https://example.com/api/helloExpected result:
Hello World
Delete the resources you created
Some resources are not free of charge. Delete the resources you no longer need to avoid paying for them: