Skip to main content

Create and manage load balancers

A load balancer receives client requests and distributes traffic across multiple servers. It is a core technology for avoiding problems that can occur when a single server handles every request.

In Kubernetes Engine, you can create and manage a load balancer by declaring Service.type=LoadBalancer and configuring spec.loadBalancerClass. Depending on the configured value, a Network Load Balancer (NLB) or Application Load Balancer (ALB) is created automatically.

Availability from August 25, 2026

This guide applies to Kubernetes Engine Services that use spec.loadBalancerClass and loadbalancer.kakaocloud.com/* annotations. These features are supported only on clusters running v1.30 or later.

  • Specify the load balancer type with spec.loadBalancerClass.
  • Use only loadbalancer.kakaocloud.com/* annotations.
  • If an existing cluster uses legacy annotations, see the legacy guide.

Create a load balancer

Scope

The protocols, annotations, and restrictions described in this guide apply to Kubernetes Engine Service integration.
They can differ from the full feature set of the KakaoCloud Load Balancing service.

Use the following procedure to create a load balancer in Kubernetes Engine.

caution

Load balancers created by Kubernetes Engine in the kr-central-2 region use a high-availability configuration. They are automatically distributed across all Availability Zones (AZs) included in the cluster network.

Even if workloads run in only some AZs, resources are allocated for the load balancer across all AZs. Load balancers created in each AZ are billable.

Prerequisites

Step 1. Install and configure kubectl

To create a Service object in Kubernetes, install kubectl and configure access to the cluster.
For instructions, see Configure kubectl.

Step 2. Register and manage SSL certificates (optional)

To terminate TLS on an ALB or NLB, configure loadbalancer.kakaocloud.com/tls-container-refs and register the SSL certificate first. Register or delete certificates in Management > Certificate Manager, and then specify the generated certificate ID in tls-container-refs.

Register a certificate
  1. In the KakaoCloud console, go to Management > Certificate Manager.
  2. On the Certificates page, select [Register certificate].
  3. Enter the required information, and then select [Register].
  4. Verify the registered certificate in the certificate list.
Delete a certificate
  1. In the KakaoCloud console, go to Management > Certificate Manager.
  2. On the Certificates page, select [More] for the certificate, and then select Delete certificate.
  3. Enter the required information, and then select [Delete].
  4. Verify that the certificate was removed from the list.

Step 1. Check the Service specification

The following fields are required to create a load balancer.

FieldValue
spec.typeLoadBalancer
spec.loadBalancerClassloadbalancer.kakaocloud.com/nlb or loadbalancer.kakaocloud.com/alb
metadata.annotationsUse the loadbalancer.kakaocloud.com/* format
NLB Service specification
NLB Service specification
kind: Service
apiVersion: v1
metadata:
name: my-nlb-service
annotations:
loadbalancer.kakaocloud.com/load-balancer-scheme: 'internal'
spec:
loadBalancerClass: loadbalancer.kakaocloud.com/nlb
selector:
app: myApp
type: LoadBalancer
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
ALB Service specification
ALB Service specification
kind: Service
apiVersion: v1
metadata:
name: my-alb-service
annotations:
loadbalancer.kakaocloud.com/load-balancer-scheme: 'internal'
loadbalancer.kakaocloud.com/tls-container-refs: 'https://key-manager.{region}/v1/secrets/{secret-id}'
spec:
loadBalancerClass: loadbalancer.kakaocloud.com/alb
selector:
app: myApp
type: LoadBalancer
ports:
- name: https
port: 443
targetPort: 443

Step 2. Select the load balancer type

Specify the load balancer type with spec.loadBalancerClass.

caution

You cannot change spec.loadBalancerClass after creating a Service. To change an existing LoadBalancer Service from NLB to ALB or vice versa, create a new Service with the required spec.loadBalancerClass value.

TypeValueDescription
NLBloadbalancer.kakaocloud.com/nlbL4 load balancer for TCP- or UDP-based services. When tls-container-refs is set, a TLS listener and TCP target group are created.
ALBloadbalancer.kakaocloud.com/albL7 load balancer that uses HTTP by default. When tls-container-refs is set, an HTTPS listener and HTTP target group are created.
info
  • For tls-container-refs, enter a certificate path in the format https://key-manager.{region}/v1/secrets/{secret-id}.
  • An ALB without a certificate uses an HTTP listener. An NLB uses a TCP or UDP listener according to the Service protocol.

Step 3. Configure public exposure

Use loadbalancer.kakaocloud.com/load-balancer-scheme to configure an internal or internet-facing load balancer.

AnnotationValueDescription
loadbalancer.kakaocloud.com/load-balancer-schemeinternalInternal load balancer that uses private addresses (default)
loadbalancer.kakaocloud.com/load-balancer-schemeinternet-facingExternal load balancer that can be publicly exposed
caution

When you set internet-facing, a new public IP is created and attached to the load balancer.
You cannot change internet-facing or internal after creation. If you used the wrong value, create a new Service with the correct setting, migrate traffic, and then delete the old Service.

If loadbalancer.kakaocloud.com/delete-floatingip is omitted or set to false, the public IP remains detached after Service deletion and can continue to incur charges.

Step 4. Create and check the Service

Apply the YAML file, and then check the Service status.

Create the Service
kubectl --kubeconfig=$KUBE_CONFIG apply -f {SERVICE_YAML_FILE}
Check the Service status
kubectl --kubeconfig=$KUBE_CONFIG get svc {SERVICE_NAME}
Check detailed Service events
kubectl --kubeconfig=$KUBE_CONFIG describe svc {SERVICE_NAME}
  • Creating the load balancer can take several minutes. While creation is in progress, EXTERNAL-IP can display Pending or an IP address can appear before creation completes.
  • Even if EXTERNAL-IP has a value, requests might fail while the load balancer or high-availability group is in the Creating state.
  • You can inspect the load balancer and high-availability group in the console. Traffic can be handled normally after all related resources enter the Active state.

Protocol mapping and restrictions

Supported protocol combinations

The following combinations are supported for Kubernetes Engine Service integration.

LB typeListener protocolTarget group protocol
ALBHTTPHTTP
ALBHTTPS (TERMINATED_HTTPS)HTTP
NLBTCPTCP
NLBTCPPROXY
NLBUDPUDP
NLBTLS (TERMINATED_HTTPS)TCP

Appendix

Complete annotation list

Configuration and management
  • Disabling health monitoring: Setting enable-health-monitor=false is not recommended in production because traffic can continue to be sent to unhealthy nodes.
  • Configuration reconciliation: If you directly change a setting controlled by the Service spec or annotations in the console, a Kubernetes resource change or controller reconciliation can restore the value defined in the Service. Make changes through the Kubernetes resource.
  • Mixing annotations: Mixing ALB-only and NLB-only annotations can prevent normal operation.
  • Traffic loss: A delay between pod termination and load balancer or service endpoint updates can cause temporary traffic loss. The effect can be greater with externalTrafficPolicy: Local because external traffic is sent only to node-local endpoints. Configure a preStop hook and sufficient terminationGracePeriodSeconds to allow draining before termination. The recommended wait time is at least the LB health check propagation time (health-monitor-delay × health-monitor-max-retries). For more information, see the Kubernetes documentation.

The following loadbalancer.kakaocloud.com/* annotations are available on current-version clusters.

Notation

Select a Details link to review the supported values, defaults, and considerations for an annotation.

Complete annotation list

ScopeAnnotationDescriptionDetails
ALBx-forwarded-forConfigure client IP forwardingDetails
ALBx-forwarded-portAdd the client port headerDetails
ALBx-forwarded-protoAdd the client protocol headerDetails
NLBproxy-protocolForward client information in a PROXY headerDetails
Commontls-container-refsConfigure certificates for TLS terminationDetails
Commontls-minimum-versionSet the minimum TLS versionDetails
Commonload-balancer-schemeConfigure an internal or external load balancerDetails
Commondelete-floatingipDelete the public IP with the ServiceDetails
Commonenable-health-monitorEnable health checksDetails
Commonhealth-monitor-http-versionSet the health check HTTP versionDetails
Commonhealth-monitor-protocolSet the health check protocolDetails
Commonhealth-monitor-delaySet the health check intervalDetails
Commonhealth-monitor-timeoutSet the health check timeoutDetails
Commonhealth-monitor-max-retriesSet successful health check retriesDetails
Commonhealth-monitor-max-retries-downSet failed health check retriesDetails
Commonhealth-monitor-url-pathSet the HTTP/HTTPS health check pathDetails
Commonhealth-monitor-http-methodSet the health check methodDetails
Commonhealth-monitor-expected-codeSet the expected response status codeDetails
Commontimeout-client-dataSet the client idle timeoutDetails
Commontimeout-member-dataSet the member idle timeoutDetails
Commonload-balancer-subnet-idsSelect load balancer subnetsDetails
Commonblb-nameSet the high-availability group nameDetails
Commonnode-selectorFilter load balancer member nodesDetails
Commonlb-methodSet the target group traffic distribution algorithmDetails

ALB-only annotations

x-forwarded-for
FieldDetails
Annotationloadbalancer.kakaocloud.com/x-forwarded-for
DescriptionConfigures how client IPs are handled in the X-Forwarded-For header.
Values/default"append" / "preserve" / "remove"; default: "append"
Changes/notesCan be changed after Service creation.
x-forwarded-port
FieldDetails
Annotationloadbalancer.kakaocloud.com/x-forwarded-port
DescriptionConfigures whether to add the client connection port to the X-Forwarded-Port header.
Values/default"true" / "false"; default: "false"
Changes/notesCan be changed after Service creation.
x-forwarded-proto
FieldDetails
Annotationloadbalancer.kakaocloud.com/x-forwarded-proto
DescriptionConfigures whether to add the client connection protocol to the X-Forwarded-Proto header.
Values/default"true" / "false"; default: "false"
Changes/notesCan be changed after Service creation.

NLB-only annotations

proxy-protocol
FieldDetails
Annotationloadbalancer.kakaocloud.com/proxy-protocol
DescriptionForwards the original client IP and port in a PROXY header.
Values/default"true" / "false"; no default
Changes/notesCannot be changed after Service creation. Create a new Service to change it.

Common annotations

tls-container-refs
FieldDetails
Annotationloadbalancer.kakaocloud.com/tls-container-refs
DescriptionSpecifies certificates for TLS termination on an ALB or NLB.
Values/default"https://key-manager.{region}/v1/secrets/{secret-id}"; no default
Changes/notesOnly an annotation specified at Service creation can be updated; adding or removing it later is not supported. Specify up to six unique certificates, separated by commas. The first is the default certificate and the others are optional certificates. Configuring it at creation is recommended.
tls-minimum-version
FieldDetails
Annotationloadbalancer.kakaocloud.com/tls-minimum-version
DescriptionSets the minimum TLS version allowed for connections.
Values/default"TLSv1" / "TLSv1.1" / "TLSv1.2" / "TLSv1.3"; default: "TLSv1.3"
Changes/notesCan be changed after Service creation. Applies to an ALB or NLB that terminates TLS.
load-balancer-scheme
FieldDetails
Annotationloadbalancer.kakaocloud.com/load-balancer-scheme
DescriptionConfigures an internal or external load balancer.
Values/default"internal" / "internet-facing"; default: "internal"
Changes/notesCannot be changed after Service creation. Create a new Service to change it.
delete-floatingip
FieldDetails
Annotationloadbalancer.kakaocloud.com/delete-floatingip
DescriptionConfigures whether to delete the attached public IP when the Service is deleted.
Values/default"true" / "false"; default: "false"
Changes/notesCan be changed after Service creation and takes effect on deletion. Valid only for an internet-facing load balancer.
enable-health-monitor
FieldDetails
Annotationloadbalancer.kakaocloud.com/enable-health-monitor
DescriptionEnables or disables health checks.
Values/default"true" / "false"; default: "true"
Changes/notesCan be changed after Service creation. false is not recommended in production because traffic can continue to be sent to unhealthy nodes.
health-monitor-http-version
FieldDetails
Annotationloadbalancer.kakaocloud.com/health-monitor-http-version
DescriptionSets the HTTP version used for health checks.
Values/default"1.1" / "1.0"; no default
Changes/notesCan be changed after Service creation.
health-monitor-protocol
FieldDetails
Annotationloadbalancer.kakaocloud.com/health-monitor-protocol
DescriptionSets the health check protocol.
Values/default"TCP" / "HTTP" / "HTTPS" / "PING" / "UDP-CONNECT"; default: "HTTP"
Changes/notesCan be changed after Service creation. Changing it deletes the existing health monitor and creates a new one. A non-default protocol can cause traffic loss during node scale-in.
health-monitor-delay
FieldDetails
Annotationloadbalancer.kakaocloud.com/health-monitor-delay
DescriptionSets the health check interval in seconds.
Values/defaultInteger; default: "5"
Changes/notesCan be changed after Service creation. Must be greater than or equal to health-monitor-timeout.
health-monitor-timeout
FieldDetails
Annotationloadbalancer.kakaocloud.com/health-monitor-timeout
DescriptionSets the health check timeout in seconds.
Values/defaultInteger; default: "5"
Changes/notesCan be changed after Service creation. Must be less than or equal to health-monitor-delay.
health-monitor-max-retries
FieldDetails
Annotationloadbalancer.kakaocloud.com/health-monitor-max-retries
DescriptionSets the number of successful retries required for a state transition.
Values/defaultInteger; default: "1"
Changes/notesCan be changed after Service creation.
health-monitor-max-retries-down
FieldDetails
Annotationloadbalancer.kakaocloud.com/health-monitor-max-retries-down
DescriptionSets the number of failed health checks required for a state transition.
Values/defaultInteger; default: "6"
Changes/notesCan be changed after Service creation.
health-monitor-url-path
FieldDetails
Annotationloadbalancer.kakaocloud.com/health-monitor-url-path
DescriptionSets the health check path.
Values/defaultString; default: "/healthz"
Changes/notesCan be changed after Service creation. Applies only when the protocol is HTTP or HTTPS.
health-monitor-http-method
FieldDetails
Annotationloadbalancer.kakaocloud.com/health-monitor-http-method
DescriptionSets the health check method.
Values/default"GET" / "HEAD" / "OPTIONS" / "POST" / "PUT" / "TRACE" / "PATCH" / "DELETE" / "CONNECT"; default: "GET"
Changes/notesCan be changed after Service creation. Applies only when the protocol is HTTP or HTTPS.
health-monitor-expected-code
FieldDetails
Annotationloadbalancer.kakaocloud.com/health-monitor-expected-code
DescriptionSets the expected response status code for a health check.
Values/defaultInteger from 100 through 999; default: "200"
Changes/notesCan be changed after Service creation. Applies only when the protocol is HTTP or HTTPS.
timeout-client-data
FieldDetails
Annotationloadbalancer.kakaocloud.com/timeout-client-data
DescriptionSets the idle timeout between the client and load balancer.
Values/defaultInteger from 1000 through 4000000 ms; default: "50000"
Changes/notesCan be changed after Service creation.
timeout-member-data
FieldDetails
Annotationloadbalancer.kakaocloud.com/timeout-member-data
DescriptionSets the idle timeout between the load balancer and member.
Values/defaultInteger from 1000 through 4000000 ms; default: "50000"
Changes/notesCan be changed after Service creation.
load-balancer-subnet-ids
FieldDetails
Annotationloadbalancer.kakaocloud.com/load-balancer-subnet-ids
DescriptionSpecifies the subnets in which the load balancer is created.
Values/defaultComma-separated subnet IDs such as "{subnet-id}"; no default
Changes/notesApplied only at Service creation. Later changes do not affect the existing load balancer. When multiple subnets are specified, the first subnet for each AZ takes priority. For an unspecified AZ, a subnet from the cluster configuration is selected automatically.
blb-name
FieldDetails
Annotationloadbalancer.kakaocloud.com/blb-name
DescriptionSets the high-availability group name.
Values/defaultString of 4–26 alphanumeric characters and hyphens; no default
Changes/notesApplied only at Service creation and only in regions that support high-availability groups. Later changes do not affect the existing load balancer.
node-selector
FieldDetails
Annotationloadbalancer.kakaocloud.com/node-selector
DescriptionFilters nodes used as load balancer target group members.
Values/defaultList of key or key=value expressions; no default
Changes/notesCan be changed after Service creation. Reconfiguring members can temporarily affect traffic. Only nodes whose labels include every specified expression are used.
lb-method
FieldDetails
Annotationloadbalancer.kakaocloud.com/lb-method
DescriptionSets the target group traffic distribution algorithm.
Values/default"ROUND_ROBIN" / "SOURCE_IP" / "LEAST_CONNECTIONS"; no default
Changes/notesCan be changed after Service creation. Applying the target group change can temporarily affect traffic.

Kubernetes Service annotation changes

caution

Current-version clusters do not support legacy annotations. When creating or updating a Service, use the current annotations in the following table.

FeatureLegacy annotationCurrent annotation
LB typeloadbalancer.ke.kakaocloud.com/load-balancer-typeCannot be set with an annotation. Use spec.loadBalancerClass (loadbalancer.kakaocloud.com/nlb or loadbalancer.kakaocloud.com/alb).
Public IP usageservice.beta.kubernetes.io/openstack-internal-load-balancerloadbalancer.kakaocloud.com/load-balancer-scheme
TLS certificateloadbalancer.openstack.org/default-tls-container-refloadbalancer.kakaocloud.com/tls-container-refs
X-Forwarded-Forloadbalancer.openstack.org/x-forwarded-forloadbalancer.kakaocloud.com/x-forwarded-for
Proxy Protocolloadbalancer.openstack.org/proxy-protocolloadbalancer.kakaocloud.com/proxy-protocol
Client idle timeoutloadbalancer.openstack.org/timeout-client-dataloadbalancer.kakaocloud.com/timeout-client-data
Member idle timeoutloadbalancer.openstack.org/timeout-member-dataloadbalancer.kakaocloud.com/timeout-member-data
Health checksloadbalancer.openstack.org/enable-health-monitorloadbalancer.kakaocloud.com/enable-health-monitor
Health check delay, timeout, and retriesloadbalancer.openstack.org/health-monitor-*loadbalancer.kakaocloud.com/health-monitor-*
LB algorithmloadbalancer.openstack.org/lb-methodloadbalancer.kakaocloud.com/lb-method
Subnetsloadbalancer.ke.kakaocloud.com/load-balancer-subnet-idsloadbalancer.kakaocloud.com/load-balancer-subnet-ids
High-availability group nameloadbalancer.ke.kakaocloud.com/blb-nameloadbalancer.kakaocloud.com/blb-name
Public IP deletion policyloadbalancer.ke.kakaocloud.com/delete-floatingiploadbalancer.kakaocloud.com/delete-floatingip
info

Do not use loadbalancer.ke.kakaocloud.com/*, loadbalancer.openstack.org/*, or service.beta.kubernetes.io/openstack-internal-load-balancer on current-version clusters.

All-options examples

NLB (all options)
NLB all-options example
kind: Service
apiVersion: v1
metadata:
name: my-nlb-service
annotations:
loadbalancer.kakaocloud.com/load-balancer-scheme: 'internet-facing'
loadbalancer.kakaocloud.com/tls-container-refs: 'https://key-manager.kr-central-2.kakaoi.io/v1/secrets/bf89955a-98b2-4cd0-b103-29607c570df1'
loadbalancer.kakaocloud.com/tls-minimum-version: 'TLSv1.3'
loadbalancer.kakaocloud.com/delete-floatingip: 'true'
loadbalancer.kakaocloud.com/proxy-protocol: 'v1'
loadbalancer.kakaocloud.com/enable-health-monitor: 'true'
loadbalancer.kakaocloud.com/health-monitor-http-version: '1.1'
loadbalancer.kakaocloud.com/health-monitor-protocol: 'http'
loadbalancer.kakaocloud.com/health-monitor-http-method: 'GET'
loadbalancer.kakaocloud.com/health-monitor-expected-code: '200'
loadbalancer.kakaocloud.com/health-monitor-url-path: '/healthz'
loadbalancer.kakaocloud.com/health-monitor-delay: '600'
loadbalancer.kakaocloud.com/health-monitor-timeout: '300'
loadbalancer.kakaocloud.com/health-monitor-max-retries: '10'
loadbalancer.kakaocloud.com/health-monitor-max-retries-down: '6'
loadbalancer.kakaocloud.com/timeout-client-data: '10000'
loadbalancer.kakaocloud.com/timeout-member-data: '10000'
loadbalancer.kakaocloud.com/node-selector: 'env,foo=bar'
loadbalancer.kakaocloud.com/lb-method: 'ROUND_ROBIN'
loadbalancer.kakaocloud.com/load-balancer-subnet-ids: 'subnet-id1,subnet-id2'
spec:
loadBalancerClass: 'loadbalancer.kakaocloud.com/nlb'
type: LoadBalancer
selector:
app: myApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
ALB (all options)
ALB all-options example
kind: Service
apiVersion: v1
metadata:
name: my-alb-service
annotations:
loadbalancer.kakaocloud.com/load-balancer-scheme: 'internet-facing'
loadbalancer.kakaocloud.com/x-forwarded-for: 'true'
loadbalancer.kakaocloud.com/x-forwarded-port: 'true'
loadbalancer.kakaocloud.com/x-forwarded-proto: 'true'
loadbalancer.kakaocloud.com/tls-container-refs: 'https://key-manager.kr-central-2.kakaoi.io/v1/secrets/bf89955a-98b2-4cd0-b103-29607c570df1,https://key-manager.kr-central-2.kakaoi.io/v1/secrets/650819f7-49dc-4cca-ad09-062d26359bab'
loadbalancer.kakaocloud.com/tls-minimum-version: 'TLSv1.3'
loadbalancer.kakaocloud.com/delete-floatingip: 'true'
loadbalancer.kakaocloud.com/enable-health-monitor: 'true'
loadbalancer.kakaocloud.com/health-monitor-http-version: '1.1'
loadbalancer.kakaocloud.com/health-monitor-protocol: 'http'
loadbalancer.kakaocloud.com/health-monitor-http-method: 'GET'
loadbalancer.kakaocloud.com/health-monitor-expected-code: '200'
loadbalancer.kakaocloud.com/health-monitor-url-path: '/healthz'
loadbalancer.kakaocloud.com/health-monitor-delay: '600'
loadbalancer.kakaocloud.com/health-monitor-timeout: '300'
loadbalancer.kakaocloud.com/health-monitor-max-retries: '10'
loadbalancer.kakaocloud.com/health-monitor-max-retries-down: '6'
loadbalancer.kakaocloud.com/timeout-client-data: '10000'
loadbalancer.kakaocloud.com/timeout-member-data: '10000'
loadbalancer.kakaocloud.com/node-selector: 'env,foo=bar'
loadbalancer.kakaocloud.com/lb-method: 'ROUND_ROBIN'
loadbalancer.kakaocloud.com/load-balancer-subnet-ids: 'subnet-id1,subnet-id2'
spec:
loadBalancerClass: 'loadbalancer.kakaocloud.com/alb'
type: LoadBalancer
selector:
app: myApp
ports:
- name: http
port: 80
targetPort: 80

Delete a LoadBalancer-type Service

Deleting a Service of type LoadBalancer also deletes the associated load balancer.

Delete the Service
kubectl --kubeconfig=$KUBE_CONFIG delete svc {SERVICE_NAME}
  • If loadbalancer.kakaocloud.com/delete-floatingip is "false", the public IP is detached when the load balancer is deleted.
  • If loadbalancer.kakaocloud.com/delete-floatingip is "true", the attached public IP is deleted with the load balancer.
  • An internal load balancer has no public IP, so delete-floatingip does not apply.