diff --git a/mkdocs.yml b/mkdocs.yml index 4688e7f585..65639e3cab 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,11 +5,19 @@ site_dir: site docs_dir: site-src extra: trademark: https://www.linuxfoundation.org/legal/trademark-usage + alternate: + - name: English + link: / + lang: en + - name: 한국어 (Korean) + link: /ko/ + lang: ko extra_css: - stylesheets/extra.css extra_javascript: - https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js - js/implementations.js + - js/language-switch.js hooks: - hack/mkdocs-copy-geps.py - hack/mkdocs-generate-conformance.py @@ -28,6 +36,7 @@ theme: - navigation.expand palette: primary: custom + language: en custom_dir: site-src/overrides edit_uri: edit/main/site-src/ plugins: @@ -188,6 +197,128 @@ nav: - Enhancement Requests: contributing/enhancement-requests.md - Release Cycle: contributing/release-cycle.md - Contributor Ladder: contributing/contributor-ladder.md + - 개요: + - 소개: ko/index.md + - 개념: + - API 개요: ko/concepts/api-overview.md + - 호환성: ko/concepts/conformance.md + - 역할과 페르소나: ko/concepts/roles-and-personas.md + - 보안 모델: ko/concepts/security-model.md + - 도구: ko/concepts/tooling.md + - 사용 사례: ko/concepts/use-cases.md + - 버전 관리: ko/concepts/versioning.md + - 서비스 메시: + - 개요: ko/mesh/index.md + - GAMMA 이니셔티브: ko/mesh/gamma.md + - 서비스 측면: ko/mesh/service-facets.md + - 구현: + - 목록: ko/implementations.md + - 비교: + - v1.3: ko/implementations/v1.3.md + - v1.2: ko/implementations/v1.2.md + - v1.1: ko/implementations/v1.1.md + - v1.0: ko/implementations/v1.0.md + - FAQ: ko/faq.md + - 용어집: ko/concepts/glossary.md + - 가이드: + - 사용자 가이드: + - 시작하기: ko/guides/index.md + - 간단한 게이트웨이: ko/guides/simple-gateway.md + - HTTP 라우팅: ko/guides/http-routing.md + - HTTP 리디렉션 및 재작성: ko/guides/http-redirect-rewrite.md + - HTTP 헤더 수정자: ko/guides/http-header-modifier.md + - HTTP 트래픽 분할: ko/guides/traffic-splitting.md + - HTTP 요청 미러링: ko/guides/http-request-mirroring.md + - 네임스페이스 간 라우팅: ko/guides/multiple-ns.md + - TLS: ko/guides/tls.md + - TCP 라우팅: ko/guides/tcp.md + - gRPC 라우팅: ko/guides/grpc-routing.md + - Ingress에서 마이그레이션: ko/guides/migrating-from-ingress.md + - 백엔드 프로토콜 선택: ko/guides/backend-protocol.md + - 인프라 속성: ko/guides/infrastructure.md + - API 설계: ko/guides/api-design.md + - CRD 관리: ko/guides/crd-management.md + - 구현자 가이드: ko/guides/implementers.md + - 참조: + - API 타입: + - Gateway: ko/api-types/gateway.md + - GatewayClass: ko/api-types/gatewayclass.md + - GRPCRoute: ko/api-types/grpcroute.md + - HTTPRoute: ko/api-types/httproute.md + - 정책: + - BackendTLSPolicy: ko/api-types/backendtlspolicy.md + - BackendTrafficPolicy: ko/api-types/backendtrafficpolicy.md + - ReferenceGrant: ko/api-types/referencegrant.md + - API 명세: + - 표준: ko/reference/spec.md + - 실험적: ko/reference/specx.md + - 정책 연결: ko/reference/policy-attachment.md + - 개선 사항: + - 개요: ko/geps/overview.md + - 임시: + - ko/geps/gep-1494/index.md + - ko/geps/gep-1651/index.md + - ko/geps/gep-2648/index.md + - ko/geps/gep-3379/index.md + - ko/geps/gep-3792/index.md + - ko/geps/gep-3793/index.md + - 구현 가능: + - ko/geps/gep-91/index.md + - ko/geps/gep-3567/index.md + - 실험적: + - ko/geps/gep-995/index.md + - ko/geps/gep-1619/index.md + - ko/geps/gep-1713/index.md + - ko/geps/gep-1731/index.md + - ko/geps/gep-1748/index.md + - ko/geps/gep-1767/index.md + - ko/geps/gep-1897/index.md + - ko/geps/gep-2162/index.md + - ko/geps/gep-2649/index.md + - ko/geps/gep-3155/index.md + - ko/geps/gep-3388/index.md + - ko/geps/gep-3567/index.md + - 표준: + - ko/geps/gep-709/index.md + - ko/geps/gep-718/index.md + - ko/geps/gep-724/index.md + - ko/geps/gep-726/index.md + - ko/geps/gep-746/index.md + - ko/geps/gep-820/index.md + - ko/geps/gep-851/index.md + - ko/geps/gep-957/index.md + - ko/geps/gep-1016/index.md + - ko/geps/gep-1294/index.md + - ko/geps/gep-1323/index.md + - ko/geps/gep-1364/index.md + - ko/geps/gep-1686/index.md + - ko/geps/gep-1709/index.md + - ko/geps/gep-1742/index.md + - ko/geps/gep-1762/index.md + - ko/geps/gep-1867/index.md + - ko/geps/gep-1911/index.md + - ko/geps/gep-2257/index.md + - ko/geps/gep-3171/index.md + - 메모: + - ko/geps/gep-713/index.md + - ko/geps/gep-917/index.md + - ko/geps/gep-922/index.md + - ko/geps/gep-1324/index.md + - ko/geps/gep-2659/index.md + - ko/geps/gep-2722/index.md + - ko/geps/gep-2907/index.md + - 거부됨: + - ko/geps/gep-735/index.md + - ko/geps/gep-1282/index.md + - 기여: + - 참여 방법: ko/contributing/index.md + - 개발자 가이드: ko/contributing/devguide.md + - 문서 스타일 가이드: ko/contributing/style-guide.md + - 개선 요청: ko/contributing/enhancement-requests.md + - 릴리스 주기: ko/contributing/release-cycle.md + - 기여자 사다리: ko/contributing/contributor-ladder.md not_in_nav: | /blog/* /geps/gep-696/* + /ko/blog/* + /ko/geps/gep-696/* diff --git a/site-src/js/language-switch.js b/site-src/js/language-switch.js new file mode 100644 index 0000000000..8827703028 --- /dev/null +++ b/site-src/js/language-switch.js @@ -0,0 +1,142 @@ +(function() { + 'use strict'; + + let cachedElements = {}; + + function getCachedElement(selector, parent = document) { + if (!cachedElements[selector]) { + cachedElements[selector] = parent.querySelector(selector); + } + return cachedElements[selector]; + } + + // Check current language + const isKorean = window.location.pathname.startsWith('/ko/'); + + // Language switching function + function switchLanguage(lang) { + const currentPath = window.location.pathname; + let newPath; + + if (lang === 'ko') { + if (currentPath.startsWith('/ko/')) return; + newPath = '/ko' + currentPath; + } else { + if (currentPath.startsWith('/ko/')) { + newPath = currentPath.substring(3); + } else return; + } + + // Set cookie and navigate to new page + document.cookie = `preferred_language=${lang}; path=/; max-age=31536000`; + window.location.href = newPath; + } + + // Update language selector + function updateLanguageSelector() { + const langButton = getCachedElement('.md-header__button[aria-label="Select language"]'); + if (!langButton) return; + + const currentLangText = isKorean ? '한국어 (Korean)' : 'English'; + + // Use CSS classes for style control + document.body.className = document.body.className.replace(/(^|\s)(is-korean|is-english)(\s|$)/g, ' ').trim() + + (isKorean ? ' is-korean' : ' is-english'); + + // Update existing text or create new one + let langText = langButton.querySelector('.lang-text'); + if (!langText) { + const icon = langButton.querySelector('svg'); + if (icon) { + icon.style.display = 'none'; + langText = document.createElement('span'); + langText.className = 'lang-text'; + langButton.appendChild(langText); + } + } + + if (langText) { + langText.textContent = currentLangText; + } + + langButton.classList.add('current-language'); + updateDropdownMenu(); + } + + // Update dropdown menu + function updateDropdownMenu() { + const dropdown = getCachedElement('.md-select__inner'); + if (!dropdown) return; + + const links = dropdown.querySelectorAll('.md-select__link'); + + links.forEach(link => { + const href = link.getAttribute('href'); + + if (href === '/' || href === './') { + link.textContent = 'English'; + link.classList.toggle('current', !isKorean); + } else if (href === '/ko/' || href.startsWith('/ko/')) { + link.textContent = '한국어 (Korean)'; + link.classList.toggle('current', isKorean); + } + + // Add event listener + if (!link.hasAttribute('data-lang-listener')) { + link.setAttribute('data-lang-listener', 'true'); + link.addEventListener('click', function(e) { + const targetIsKorean = href.startsWith('/ko/'); + + if (isKorean === targetIsKorean) { + e.preventDefault(); + return; + } + + const targetLang = targetIsKorean ? 'ko' : 'en'; + document.cookie = `preferred_language=${targetLang}; path=/; max-age=31536000`; + }); + } + }); + } + + // Initialization function + function init() { + updateLanguageSelector(); + + // Detect dynamic content with MutationObserver + const observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { + // Update only when new language links are added + for (let node of mutation.addedNodes) { + if (node.nodeType === 1 && node.matches && node.matches('.md-select__link')) { + updateDropdownMenu(); + break; + } + } + } + }); + }); + + // Observe language selector container + const selectContainer = getCachedElement('.md-select'); + if (selectContainer) { + observer.observe(selectContainer, { + childList: true, + subtree: true + }); + } + } + + // Execute immediately when DOM is ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + // Execute immediately if already loaded + init(); + } + + // Expose global function + window.switchLanguage = switchLanguage; + +})(); \ No newline at end of file diff --git a/site-src/ko/.mkdocs-exclude b/site-src/ko/.mkdocs-exclude new file mode 100644 index 0000000000..9a2dd762e5 --- /dev/null +++ b/site-src/ko/.mkdocs-exclude @@ -0,0 +1,6 @@ +.mkdocs-exclude +.nojekyll +.placeholder +search/search_index.json +sitemap.xml.gz +sitemap.xml diff --git a/site-src/ko/OWNERS b/site-src/ko/OWNERS new file mode 100644 index 0000000000..f866d12bd1 --- /dev/null +++ b/site-src/ko/OWNERS @@ -0,0 +1,10 @@ +# See the OWNERS docs at https://go.k8s.io/owners +# See the OWNERS_ALIASES file at https://github.com/kubernetes-sigs/gateway-api/blob/main/OWNERS_ALIASES for a list of members for each alias. + +approvers: + - sig-network-leads + - gateway-api-maintainers + +reviewers: + - gateway-api-maintainers + - gateway-api-mesh-leads diff --git a/site-src/ko/api-types/backendtlspolicy.md b/site-src/ko/api-types/backendtlspolicy.md new file mode 100644 index 0000000000..ac57bd04ec --- /dev/null +++ b/site-src/ko/api-types/backendtlspolicy.md @@ -0,0 +1,148 @@ +# BackendTLSPolicy + +??? example "Experimental Channel since v1.0.0" + + The `BackendTLSPolicy` resource is Alpha and has been part of + the Experimental Channel since `v1.0.0`. For more information on release + channels, refer to our [versioning guide](../concepts/versioning.md). + +[BackendTLSPolicy][backendtlspolicy] is a Gateway API type for specifying the TLS configuration +of the connection from the Gateway to a backend pod/s via the Service API object. + +## Background + +`BackendTLSPolicy` specifically addresses the configuration of TLS in order to convey HTTPS from the Gateway +dataplane to the backend. This is referred to as "backend TLS termination" and enables the Gateway to know +how to connect to a backend pod that has its own certificate. + +While there are other API objects provided for TLS to be configured for **passthrough** and **edge** termination, +this API object allows users to specifically configure **backend** TLS termination. For more information on TLS +configuration in Gateway API, see [TLS Configuration](../guides/tls.md). + +![Image showing three TLS Termination Types](../images/tls-termination-types.png) + +BackendTLSPolicy is a Direct [PolicyAttachment](../reference/policy-attachment.md) without defaults or overrides, +applied to a Service that accesses a backend, where the BackendTLSPolicy resides in the same namespace as the +Service to which it is applied. The BackendTLSPolicy and the Service must reside in the same namespace in order +to prevent the complications involved with sharing trust across namespace boundaries. + +All Gateway API Routes that point to a referenced Service should respect a configured BackendTLSPolicy. + +## Spec + +The specification of a [BackendTLSPolicy][backendtlspolicy] consists of: + +- [TargetRefs][targetRefs] - Defines the targeted API object of the policy. Only Service is allowed. +- [Validation][validation] - Defines the configuration for TLS, including hostname, CACertificateRefs, and +WellKnownCACertificates. +- [Hostname][hostname] - Defines the Server Name Indication (SNI) that the Gateway uses to connect to the backend. +- [CACertificateRefs][caCertificateRefs] - Defines one or more references to objects that contain PEM-encoded TLS certificates, +which are used to establish a TLS handshake between the Gateway and backend Pod. Either CACertificateRefs or +WellKnownCACertificates may be specified, but not both. +- [WellKnownCACertificates][wellKnownCACertificates] - Specifies whether system CA certificates may be used in the TLS +handshake between the Gateway and backend Pod. Either CACertificateRefs or WellKnownCACertificates may be specified, but not both. + +The following chart outlines the object definitions and relationship: +```mermaid +flowchart LR + backendTLSPolicy[["backendTLSPolicy
BackendTLSPolicySpec: spec
PolicyStatus: status"]] + spec[["spec
PolicyTargetReferenceWithSectionName: targetRefs
BackendTLSPolicyValidation: tls"]] + status[["status
[ ]PolicyAncestorStatus: ancestors"]] + validation[["tls
LocalObjectReference: caCertificateRefs
wellKnownCACertificatesType: wellKnownCACertificates/
PreciseHostname: hostname"]] + ancestorStatus[["ancestors
AncestorRef: parentReference
GatewayController: controllerName
[]Condition: conditions"]] + targetRefs[[targetRefs
]] + service["service"] + backendTLSPolicy -->spec + backendTLSPolicy -->status + spec -->targetRefs & validation + status -->ancestorStatus + targetRefs -->service + note[choose only one
caCertificateRefs OR wellKnownCACertificates
] + style note fill:#fff + validation -.- note +``` + +The following illustrates a BackendTLSPolicy that configures TLS for a Service serving a backend: +```mermaid +flowchart LR + client(["client"]) + gateway["Gateway"] + style gateway fill:#02f,color:#fff + httproute["HTTP
Route"] + style httproute fill:#02f,color:#fff + service["Service"] + style service fill:#02f,color:#fff + pod1["Pod"] + style pod1 fill:#02f,color:#fff + pod2["Pod"] + style pod2 fill:#02f,color:#fff + client -.->|HTTP
request| gateway + gateway --> httproute + httproute -.->|BackendTLSPolicy|service + service --> pod1 & pod2 +``` + +### Targeting backends + +A BackendTLSPolicy targets a backend Pod (or set of Pods) via one or more TargetRefs to a Service. This TargetRef is a +required object reference that specifies a Service by its Name, Kind (Service), and optionally its Namespace and Group. +TargetRefs identify the Service/s for which your HTTPRoute requires TLS. + +!!! info "Restrictions" + + - Cross-namespace certificate references are not allowed. + +### BackendTLSPolicyValidation + +A BackendTLSPolicyValidation is the specification for the BackendTLSPolicy and defines the configuration for TLS, +including hostname (for server name indication) and certificates. + +#### Hostname + +Hostname defines the server name indication (SNI) the Gateway should use in order to connect to the backend, and must +match the certificate served by the backend pod. A hostname is the fully qualified domain name of a network host, as +defined by [RFC 3986][rfc-3986]. Note the following deviations from the “host” part of the URI as defined in the RFC: + +- IP addresses are not allowed. + +Also note: + +!!! info "Restrictions" + + - Wildcard hostnames are not allowed. + +#### Certificates + +The BackendTLSPolicyValidation must contain a certificate reference of some kind, and contains two ways to configure the +certificate to use for backend TLS, CACertificateRefs and WellKnownCACertificates. Only one of these may be used per +BackendTLSPolicyValidation. + +##### CACertificateRefs + +CACertificateRefs refer to one or more PEM-encoded TLS certificates. + +!!! info "Restrictions" + + - Cross-namespace certificate references are not allowed. + +##### WellKnownCACertificates + +If you are working in an environment where specific TLS certificates are not required, and your Gateway API +implementation allows system or default certificates to be used, e.g. in a development environment, you may +set WellKnownCACertificates to "System" to tell the Gateway to use a set of trusted CA Certificates. There may be +some variation in which system certificates are used by each implementation. Refer to documentation from your +implementation of choice for more information. + +### PolicyStatus + +Status defines the observed state of the BackendTLSPolicy and is not user-configurable. Check status in the same +way you do for other Gateway API objects to verify correct operation. Note that the status in BackendTLSPolicy +uses `PolicyAncestorStatus` to allow you to know which parentReference set that particular status. + +[backendtlspolicy]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicy +[validation]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicy.Validation +[caCertificateRefs]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicyValidation.CACertificateRefs +[wellKnownCACertificates]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha3.BackendTLSPolicyValidation.WellKnownCACertificates +[hostname]: ../reference/spec.md#gateway.networking.k8s.io/v1.PreciseHostname +[rfc-3986]: https://tools.ietf.org/html/rfc3986 +[targetRefs]: ../reference/spec.md#gateway.networking.k8s.io/v1alpha2.PolicyTargetReference diff --git a/site-src/ko/api-types/backendtrafficpolicy.md b/site-src/ko/api-types/backendtrafficpolicy.md new file mode 100644 index 0000000000..61dd645229 --- /dev/null +++ b/site-src/ko/api-types/backendtrafficpolicy.md @@ -0,0 +1,93 @@ +# BackendTrafficPolicy + +??? example "Experimental Channel since v1.3.0" + + The `BackendTrafficPolicy` resource is a part of the Experimental Channel + since `v1.3.0`. For more information on release channels, refer to our + [versioning guide](../concepts/versioning.md). + +[BackendTrafficPolicy][backendtrafficpolicy] is a Gateway API type to configure +the behavior of clients when targeting a valid backend resource. + +## Background + +`BackendTrafficPolicy` is used to configure the behavior of clients when making +requests targeting a backend, a grouping of like endpoints. Currently, this +policy includes the ability to configure a `RetryConstraint`, which can +dynamically limit the number of active retries targeting the specified backend, +by defining a "retry budget". Additional features may be added in the future. + +### Retry Constraint + +While client-side retries are important for allowing requests to be +successfully retried in +periods of intermittent failure, excessive retries can quickly overwhelm a +system, leading to cascading failures such as retry storms. Specifying a +`RetryConstraint` within `BackendTrafficPolicy` allows application +developers to dynamically calculate a limit on active client-side retries as a percentage of +the overall active request volume. While the retry stanza within the +[HTTPRouteRule][httproute] resource allows specifying whether a request +*should* be retried, as well as the maximum number of +retries that may be performed for a failed request, budgeted +retries instead act as a +fail-safe in order to ensure that the targeted backend will not be overwhelmed +by the *overall* volume of retries from the client. + +The retry budget is calculated based on the percentage of incoming traffic +composed of retries over a given time interval. Retrying the same original +request multiple times within the retry budget interval will lead to each retry +being counted towards calculating the budget. Once the budget is exceeded, +additional retries to the backend will be rejected and MUST return a 503 +response to the client. The parameters of the retry budget calculation can be +configured within `RetryConstraint`. + +BackendTrafficPolicy is a Direct +[PolicyAttachment](../reference/policy-attachment.md). All Gateway API Routes +that target the referenced Backend should respect a configured +BackendTrafficPolicy. Additional configurations for defining a constraint on +retries MAY be defined in the future. + + +## Spec + +The specification of a [BackendTrafficPolicy][backendtrafficpolicy] consists of: + +- [TargetRefs][localpolicytargetreference] - Defines the targeted API object(s) of the policy. + Backends (A grouping of like endpoints such as Service, + ServiceImport, or any implementation-specific backendRef) are the only valid + API target references. +- [RetryConstraint][retryConstraint] - Defines the configuration for how a retry budget should be calculated, by specifying BudgetDetails and MinRetryRate. +- [SessionPersistence][sessionPersistence] - Defines the session persistence for the backend. + +The following chart outlines the object definitions and relationship: +```mermaid +flowchart LR + backendTrafficPolicy[["backendTrafficPolicy
BackendTrafficPolicySpec: spec
PolicyStatus: status"]] + spec[["spec
LocalPolicyTargetReference: targetRefs
RetryConstraint: retryConstraint"
SessionPersistence: sessionPersistence]] + status[["status
[ ]PolicyAncestorStatus: ancestors"]] + budget[["budget
int: budgetPercent
Duration: budgetInterval"]] + retryConstraint[["retryConstraint
BudgetDetails: budget
MinRetryRate: RequestRate"]] + ancestorStatus[["ancestors
AncestorRef: parentReference
GatewayController: controllerName
[]Condition: conditions"]] + targetRefs[[targetRefs
]] + backendRef["one of:
" Service OR ServiceImport OR an implementation-specific backendRef] + backendTrafficPolicy -->spec + backendTrafficPolicy -->status + spec -->targetRefs & retryConstraint + retryConstraint -->budget + status -->ancestorStatus + targetRefs -->backendRef +``` + +### Targeting backends + +`BackendTrafficPolicy` targets a group of backend Pods via one or more +TargetRefs such as Service, ServiceImport, or implementation-specific +backendRef. TargetRefs is a required object reference, specifying a Backend via +its Name, Kind, and Group. Currently, TargetRefs can not be scoped to +specific ports on a service. + +[backendtrafficpolicy]: /references/specx.md#xbackendtrafficpolicy +[localpolicytargetreference]: /references/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReference +[retryConstraint]: /references/specx.md#retryconstraint +[sessionPersistence]: /references/spec/#gateway.networking.k8s.io/v1.SessionPersistence +[httproute]: /references/spec/#https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1beta1.HTTPRoute diff --git a/site-src/ko/api-types/gateway.md b/site-src/ko/api-types/gateway.md new file mode 100644 index 0000000000..372eab5a89 --- /dev/null +++ b/site-src/ko/api-types/gateway.md @@ -0,0 +1,53 @@ +# Gateway + +??? success "Standard Channel since v0.5.0" + + The `Gateway` resource is GA and has been part of the Standard Channel since + `v0.5.0`. For more information on release channels, refer to our [versioning + guide](../concepts/versioning.md). + +A `Gateway` is 1:1 with the lifecycle of the configuration of infrastructure. +When a user creates a `Gateway`, some load balancing infrastructure is +provisioned or configured (see below for details) by the `GatewayClass` +controller. `Gateway` is the resource that triggers actions in this API. Other +resources in this API are configuration snippets until a Gateway has been +created to link the resources together. + +The `Gateway` spec defines the following: + +* `GatewayClassName`- Defines the name of a `GatewayClass` object used by + this Gateway. +* `Listeners`- Define the hostnames, ports, protocol, termination, TLS + settings and which routes can be attached to a listener. +* `Addresses`- Define the network addresses requested for this gateway. + +If the desired configuration specified in Gateway spec cannot be achieved, the +Gateway will be in an error state with details provided by status conditions. + +### Deployment models + +Depending on the `GatewayClass`, the creation of a `Gateway` could do any of +the following actions: + +* Use cloud APIs to create an LB instance. +* Spawn a new instance of a software LB (in this or another cluster). +* Add a configuration stanza to an already instantiated LB to handle the new + routes. +* Program the SDN to implement the configuration. +* Something else we haven’t thought of yet... + +The API does not specify which one of these actions will be taken. + +### Gateway Status + +`GatewayStatus` is used to surface the status of a `Gateway` relative to the +desired state represented in `spec`. `GatewayStatus` consists of the following: + +- `Addresses`- Lists the IP addresses that have actually been bound to the + Gateway. +- `Listeners`- Provide status for each unique listener defined in `spec`. +- `Conditions`- Describe the current status conditions of the Gateway. + +Both `Conditions` and `Listeners.conditions` follow the conditions pattern used +elsewhere in Kubernetes. This is a list that includes a type of condition, the +status of the condition and the last time this condition changed. diff --git a/site-src/ko/api-types/gatewayclass.md b/site-src/ko/api-types/gatewayclass.md new file mode 100644 index 0000000000..9eb2fd674e --- /dev/null +++ b/site-src/ko/api-types/gatewayclass.md @@ -0,0 +1,145 @@ +# GatewayClass + +??? success "Standard Channel since v0.5.0" + + The `GatewayClass` resource is GA and has been part of the Standard Channel since + `v0.5.0`. For more information on release channels, refer to our [versioning + guide](../concepts/versioning.md). + +[GatewayClass][gatewayclass] is cluster-scoped resource defined by the +infrastructure provider. This resource represents a class of Gateways that can +be instantiated. + +> Note: GatewayClass serves the same function as the +> [`networking.IngressClass` resource][ingress-class-api]. + +```yaml +kind: GatewayClass +metadata: + name: cluster-gateway +spec: + controllerName: "example.net/gateway-controller" +``` + +We expect that one or more `GatewayClasses` will be created by the +infrastructure provider for the user. It allows decoupling of which mechanism +(e.g. controller) implements the `Gateways` from the user. For instance, an +infrastructure provider may create two `GatewayClasses` named `internet` and +`private` to reflect `Gateways` that define Internet-facing vs private, internal +applications. + +```yaml +kind: GatewayClass +metadata: + name: internet + ... +--- +kind: GatewayClass +metadata: + name: private + ... +``` + +The user of the classes will not need to know *how* `internet` and `private` are +implemented. Instead, the user will only need to understand the resulting +properties of the class that the `Gateway` was created with. + +### GatewayClass parameters + +Providers of the `Gateway` API may need to pass parameters to their controller +as part of the class definition. This is done using the +`GatewayClass.spec.parametersRef` field: + +```yaml +# GatewayClass for Gateways that define Internet-facing applications. +kind: GatewayClass +metadata: + name: internet +spec: + controllerName: "example.net/gateway-controller" + parametersRef: + group: example.net + kind: Config + name: internet-gateway-config +--- +apiVersion: example.net/v1alpha1 +kind: Config +metadata: + name: internet-gateway-config +spec: + ip-address-pool: internet-vips + ... +``` + +Using a Custom Resource for `GatewayClass.spec.parametersRef` is encouraged +but implementations may resort to using a ConfigMap if needed. + +### GatewayClass status + +`GatewayClasses` MUST be validated by the provider to ensure that the configured +parameters are valid. The validity of the class will be signaled to the user via +`GatewayClass.status`: + +```yaml +kind: GatewayClass +... +status: + conditions: + - type: Accepted + status: False + ... +``` + +A new `GatewayClass` will start with the `Accepted` condition set to +`False`. At this point the controller has not seen the configuration. Once the +controller has processed the configuration, the condition will be set to +`True`: + +```yaml +kind: GatewayClass +... +status: + conditions: + - type: Accepted + status: True + ... +``` + +If there is an error in the `GatewayClass.spec`, the conditions will be +non-empty and contain information about the error. + +```yaml +kind: GatewayClass +... +status: + conditions: + - type: Accepted + status: False + Reason: BadFooBar + Message: "foobar" is an FooBar. +``` + +### GatewayClass controller selection + +The `GatewayClass.spec.controller` field determines the controller implementation +responsible for managing the `GatewayClass`. The format of the field is opaque +and specific to a particular controller. The GatewayClass selected by a given +controller field depends on how various controller(s) in the cluster interpret +this field. + +It is RECOMMENDED that controller authors/deployments make their selection +unique by using a domain / path combination under their administrative control +(e.g. controller managing of all `controller`s starting with `example.net` is the +owner of the `example.net` domain) to avoid conflicts. + +Controller versioning can be done by encoding the version of a controller into +the path portion. An example scheme could be (similar to container URIs): + +```text +example.net/gateway/v1 // Use version 1 +example.net/gateway/v2.1 // Use version 2.1 +example.net/gateway // Use the default version +``` + +[gatewayclass]: ../reference/spec.md#gateway.networking.k8s.io/v1.GatewayClass +[ingress-class-api]: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class diff --git a/site-src/ko/api-types/grpcroute.md b/site-src/ko/api-types/grpcroute.md new file mode 100644 index 0000000000..2b6188ad47 --- /dev/null +++ b/site-src/ko/api-types/grpcroute.md @@ -0,0 +1,283 @@ +# GRPCRoute + +??? success "Standard Channel since v1.1.0" + + The `GRPCRoute` resource is GA and has been part of the Standard Channel since + `v1.1.0`. For more information on release channels, refer to our [versioning + guide](../concepts/versioning.md). + +[GRPCRoute][grpcroute] is a Gateway API type for specifying routing behavior +of gRPC requests from a Gateway listener to an API object, i.e. Service. + +## Background + +While it is possible to route gRPC with `HTTPRoutes` or via custom, out-of-tree +CRDs, in the long run, this leads to a fragmented ecosystem. + +gRPC is a [popular RPC framework adopted widely across the industry](https://grpc.io/about/#whos-using-grpc-and-why). +The protocol is used pervasively within the Kubernetes project itself as the basis for +many interfaces, including: + +- [the CSI](https://github.com/container-storage-interface/spec/blob/5b0d4540158a260cb3347ef1c87ede8600afb9bf/spec.md), +- [the CRI](https://github.com/kubernetes/cri-api/blob/49fe8b135f4556ea603b1b49470f8365b62f808e/README.md), +- [the device plugin framework](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/) + +Given gRPC's importance in the application-layer networking space and to +the Kubernetes project in particular, the determination was made not to allow +the ecosystem to fragment unnecessarily. + +### Encapsulated Network Protocols + +In general, when it is possible to route an encapsulated protocol at a lower +level, it is acceptable to introduce a route resource at the higher layer when +the following criteria are met: + +- Users of the encapsulated protocol would miss out on significant conventional features from their ecosystem if forced to route at a lower layer. +- Users of the encapsulated protocol would experience a degraded user experience if forced to route at a lower layer. +- The encapsulated protocol has a significant user base, particularly in the Kubernetes community. + +gRPC meets all of these criteria, so the decision was made to include `GRPCRoute`in Gateway API. + +### Cross Serving + +Implementations that support GRPCRoute must enforce uniqueness of +hostnames between `GRPCRoute`s and `HTTPRoute`s. If a route (A) of type `HTTPRoute` or +`GRPCRoute` is attached to a Listener and that listener already has another Route (B) of +the other type attached and the intersection of the hostnames of A and B is +non-empty, then the implementation must reject Route A. That is, the +implementation must raise an 'Accepted' condition with a status of 'False' in +the corresponding RouteParentStatus. + +In general, it is recommended that separate hostnames be used for gRPC and +non-gRPC HTTP traffic. This aligns with standard practice in the gRPC community. +If however, it is a necessity to serve HTTP and gRPC on the same hostname with +the only differentiator being URI, the user should use `HTTPRoute` resources for +both gRPC and HTTP. This will come at the cost of the improved UX of the +`GRPCRoute` resource. + +## Spec + +The specification of a GRPCRoute consists of: + +- [ParentRefs][parentRef]- Define which Gateways this Route wants to be attached + to. +- [Hostnames][hostname] (optional)- Define a list of hostnames to use for + matching the Host header of gRPC requests. +- [Rules][grpcrouterule]- Define a list of rules to perform actions against + matching gRPC requests. Each rule consists of [matches][matches], + [filters][filters] (optional), [backendRefs][backendRef] (optional), and + [name][name] (optional) fields. + + +The following illustrates a GRPCRoute that sends all traffic to one Service: +![grpcroute-basic-example](../images/grpcroute-basic-example.png) + +### Attaching to Gateways + +Each Route includes a way to reference the parent resources it wants to attach +to. In most cases, that's going to be Gateways, but there is some flexibility +here for implementations to support other types of parent resources. + +The following example shows how a Route would attach to the `acme-lb` Gateway: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: GRPCRoute +metadata: + name: grpcroute-example +spec: + parentRefs: + - name: acme-lb +``` + +Note that the target Gateway needs to allow GRPCRoutes from the route's +namespace to be attached for the attachment to be successful. + +### Hostnames + +Hostnames define a list of hostnames to match against the Host header of the +gRPC request. When a match occurs, the GRPCRoute is selected to perform request +routing based on rules and filters (optional). A hostname is the fully qualified +domain name of a network host, as defined by [RFC 3986][rfc-3986]. Note the +following deviations from the “host” part of the URI as defined in the RFC: + +- IPs are not allowed. +- The : delimiter is not respected because ports are not allowed. + +Incoming requests are matched against hostnames before the GRPCRoute rules are +evaluated. If no hostname is specified, traffic is routed based on GRPCRoute +rules and filters (optional). + +The following example defines hostname "my.example.com": + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: GRPCRoute +metadata: + name: grpcroute-example +spec: + hostnames: + - my.example.com +``` + +### Rules + +Rules define semantics for matching an gRPC requests based on conditions, +optionally executing additional processing steps, and optionally forwarding +the request to an API object. + +#### Matches + +Matches define conditions used for matching an gRPC requests. Each match is +independent, i.e. this rule will be matched if any single match is satisfied. + +Take the following matches configuration as an example: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: GRPCRoute +... +matches: + - method: + service: com.example.User + method: Login + headers: + - name: version + value: "2" + - method: + service: com.example.v2.User + method: Login +``` + +For a request to match against this rule, it must satisfy EITHER of the +following conditions: + + - The `com.example.User.Login` method **AND** contains the header "version: 2" + - The `com.example.v2.User.Login` method. + +If no matches are specified, the default is to match every gRPC request. + +#### Filters (optional) + +Filters define processing steps that must be completed during the request or +response lifecycle. Filters act as an extension point to express additional +processing that may be performed in Gateway implementations. Some examples +include request or response modification, implementing authentication +strategies, rate-limiting, and traffic shaping. + +The following example adds header "my-header: foo" to gRPC requests with Host +header "my.filter.com". Note that GRPCRoute uses HTTPRoute filters for features +with functionality identical to HTTPRoute, such as this. + +```yaml +{% include 'standard/grpc-filter.yaml' %} +``` + +API conformance is defined based on the filter type. The effects of ordering +multiple behaviors are currently unspecified. This may change in the future +based on feedback during the alpha stage. + +Conformance levels are defined by the filter type: + + - All "core" filters MUST be supported by implementations supporting GRPCRoute. + - Implementers are encouraged to support "extended" filters. + - "Implementation-specific" filters have no API guarantees across implementations. + +Specifying a core filter multiple times has unspecified or custom conformance. + +If an implementation cannot support a combinations of filters, they must clearly +document that limitation. In cases where incompatible or unsupported +filters are specified and cause the `Accepted` condition to be set to status +`False`, implementations may use the `IncompatibleFilters` reason to specify +this configuration error. + +#### BackendRefs (optional) + +BackendRefs defines the API objects to which matching requests should be sent. If +unspecified, the rule performs no forwarding. If unspecified and no filters +are specified that would result in a response being sent, an `UNIMPLEMENTED` error code +is returned. + +The following example forwards gRPC requests for the method `User.Login` to service +"my-service1" on port `50051` and gRPC requests for the method `Things.DoThing` with +header `magic: foo` to service "my-service2" on port `50051`: + +```yaml +{% include 'standard/basic-grpc.yaml' %} +``` + +The following example uses the `weight` field to forward 90% of gRPC requests to +`foo.example.com` to the "foo-v1" Service and the other 10% to the "foo-v2" +Service: + +```yaml +{% include 'standard/traffic-splitting/grpc-traffic-split-2.yaml' %} +``` + +Reference the [backendRef][backendRef] API documentation for additional details +on `weight` and other fields. + +#### Name (optional) + +??? example "Experimental Channel since v1.2.0" + + This concept has been part of the Experimental Channel since `v1.2.0`. + For more information on release channels, refer to our + [versioning guide](../concepts/versioning.md). + +GRPCRoute Rules include an optional `name` field. The applications for the name of a route rule are implementation-specific. It can be used to reference individual route rules by name from other resources, such as in the `sectionName` field of metaresources ([GEP-2648](../geps/gep-2648/index.md#section-names)), in the status stanzas of resources related to the route object, to identify internal configuration objects generated by the implementation from GRPCRoute Rule, etc. + +If specified, the value of the name field must comply with the [`SectionName`](https://github.com/kubernetes-sigs/gateway-api/blob/v1.0.0/apis/v1/shared_types.go#L607-L624) type. + +## Status + +Status defines the observed state of the GRPCRoute. + +### RouteStatus + +RouteStatus defines the observed state that is required across all route types. + +#### Parents + +Parents define a list of the Gateways (or other parent resources) that are +associated with the GRPCRoute, and the status of the GRPCRoute with respect to +each of these Gateways. When a GRPCRoute adds a reference to a Gateway in +parentRefs, the controller that manages the Gateway should add an entry to this +list when the controller first sees the route and should update the entry as +appropriate when the route is modified. + +## Examples + +The following example indicates GRPCRoute "grpc-example" has been accepted by +Gateway "gw-example" in namespace "gw-example-ns": + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: GRPCRoute +metadata: + name: grpc-example +... +status: + parents: + - parentRefs: + name: gw-example + namespace: gw-example-ns + conditions: + - type: Accepted + status: "True" +``` + +## Merging +Multiple GRPCRoutes can be attached to a single Gateway resource. Importantly, +only one Route rule may match each request. For more information on how conflict +resolution applies to merging, refer to the [API specification][grpcrouterule]. + +[grpcroute]: ../reference/spec.md#gateway.networking.k8s.io/v1.GRPCRoute +[grpcrouterule]: ../reference/spec.md#gateway.networking.k8s.io/v1.GRPCRouteRule +[hostname]: ../reference/spec.md#gateway.networking.k8s.io/v1.Hostname +[rfc-3986]: https://tools.ietf.org/html/rfc3986 +[matches]: ../reference/spec.md#gateway.networking.k8s.io/v1.GRPCRouteMatch +[filters]: ../reference/spec.md#gateway.networking.k8s.io/v1.GRPCRouteFilter +[backendRef]: ../reference/spec.md#gateway.networking.k8s.io/v1.GRPCBackendRef +[parentRef]: ../reference/spec.md#gateway.networking.k8s.io/v1.ParentRef +[name]: ../reference/spec.md#gateway.networking.k8s.io/v1.SectionName diff --git a/site-src/ko/api-types/httproute.md b/site-src/ko/api-types/httproute.md new file mode 100644 index 0000000000..0551a37c3d --- /dev/null +++ b/site-src/ko/api-types/httproute.md @@ -0,0 +1,349 @@ +# HTTPRoute + +??? success "Standard Channel since v0.5.0" + + The `HTTPRoute` resource is GA and has been part of the Standard Channel since + `v0.5.0`. For more information on release channels, refer to our [versioning + guide](../concepts/versioning.md). + +[HTTPRoute][httproute] is a Gateway API type for specifying routing behavior +of HTTP requests from a Gateway listener to an API object, i.e. Service. + +## Spec + +The specification of an HTTPRoute consists of: + +- [ParentRefs][parentRef]- Define which Gateways this Route wants to be attached + to. +- [Hostnames][hostname] (optional)- Define a list of hostnames to use for + matching the Host header of HTTP requests. +- [Rules][httprouterule]- Define a list of rules to perform actions against + matching HTTP requests. Each rule consists of [matches][matches], + [filters][filters] (optional), [backendRefs][backendRef] (optional), + [timeouts][timeouts] (optional), and [name][sectionName] (optional) fields. + +The following illustrates an HTTPRoute that sends all traffic to one Service: +![httproute-basic-example](../images/httproute-basic-example.svg) + +### Attaching to Gateways + +Each Route includes a way to reference the parent resources it wants to attach +to. In most cases, that's going to be Gateways, but there is some flexibility +here for implementations to support other types of parent resources. + +The following example shows how a Route would attach to the `acme-lb` Gateway: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: httproute-example +spec: + parentRefs: + - name: acme-lb +``` + +Note that the target Gateway needs to allow HTTPRoutes from the route's +namespace to be attached for the attachment to be successful. + +You can also attach routes to specific sections of the parent resource. +For example, let's say that the `acme-lb` Gateway includes the following +listeners: + +```yaml + listeners: + - name: foo + protocol: HTTP + port: 8080 + ... + - name: bar + protocol: HTTP + port: 8090 + ... + - name: baz + protocol: HTTP + port: 8090 + ... +``` + +You can bind a route to listener `foo` only, using the `sectionName` field +in `parentRefs`: + +```yaml +spec: + parentRefs: + - name: acme-lb + sectionName: foo +``` + +Alternatively, you can achieve the same effect by using the `port` field, +instead of `sectionName`, in the `parentRefs`: + +```yaml +spec: + parentRefs: + - name: acme-lb + port: 8080 +``` + +Binding to a port also allows you to attach to multiple listeners at once. +For example, binding to port `8090` of the `acme-lb` Gateway would be more +convenient than binding to the corresponding listeners by name: + +```yaml +spec: + parentRefs: + - name: acme-lb + sectionName: bar + - name: acme-lb + sectionName: baz +``` + +However, when binding Routes by port number, Gateway admins will no longer have +the flexibility to switch ports on the Gateway without also updating the Routes. +The approach should only be used when a Route should apply to a specific port +number as opposed to listeners whose ports may be changed. + +### Hostnames + +Hostnames define a list of hostnames to match against the Host header of the +HTTP request. When a match occurs, the HTTPRoute is selected to perform request +routing based on rules and filters (optional). A hostname is the fully qualified +domain name of a network host, as defined by [RFC 3986][rfc-3986]. Note the +following deviations from the “host” part of the URI as defined in the RFC: + +- IPs are not allowed. +- The : delimiter is not respected because ports are not allowed. + +Incoming requests are matched against hostnames before the HTTPRoute rules are +evaluated. If no hostname is specified, traffic is routed based on HTTPRoute +rules and filters (optional). + +The following example defines hostname "my.example.com": + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: httproute-example +spec: + hostnames: + - my.example.com +``` + +### Rules + +Rules define semantics for matching an HTTP request based on conditions, +optionally executing additional processing steps, and optionally forwarding +the request to an API object. + +#### Matches + +Matches define conditions used for matching an HTTP request. Each match is +independent, i.e. this rule will be matched if any single match is satisfied. + +Take the following matches configuration as an example: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +... +spec: + rules: + - matches: + - path: + value: "/foo" + headers: + - name: "version" + value: "2" + - path: + value: "/v2/foo" +``` + +For a request to match against this rule, it must satisfy EITHER of the +following conditions: + + - A path prefixed with /foo **AND** contains the header "version: 2" + - A path prefix of /v2/foo + +If no matches are specified, the default is a prefix path match on “/”, +which has the effect of matching every HTTP request. + +#### Filters (optional) + +Filters define processing steps that must be completed during the request or +response lifecycle. Filters act as an extension point to express additional +processing that may be performed in Gateway implementations. Some examples +include request or response modification, implementing authentication +strategies, rate-limiting, and traffic shaping. + +The following example adds header "my-header: foo" to HTTP requests with Host +header "my.filter.com". +```yaml +{% include 'standard/http-filter.yaml' %} +``` + +API conformance is defined based on the filter type. The effects of ordering +multiple behaviors is currently unspecified. This may change in the future +based on feedback during the alpha stage. + +Conformance levels are defined by the filter type: + + - All "core" filters MUST be supported by implementations. + - Implementers are encouraged to support "extended" filters. + - "Implementation-specific" filters have no API guarantees across implementations. + +Specifying a core filter multiple times has unspecified or +implementation-specific conformance. + +All filters are expected to be compatible with each other except for the +URLRewrite and RequestRedirect filters, which may not be combined. If an +implementation cannot support other combinations of filters, they must clearly +document that limitation. In cases where incompatible or unsupported +filters are specified and cause the `Accepted` condition to be set to status +`False`, implementations may use the `IncompatibleFilters` reason to specify +this configuration error. + +#### BackendRefs (optional) + +BackendRefs defines API objects where matching requests should be sent. If +unspecified, the rule performs no forwarding. If unspecified and no filters +are specified that would result in a response being sent, a 404 error code +is returned. + +The following example forwards HTTP requests for path prefix `/bar` to service +"my-service1" on port `8080`, and HTTP requests fulfilling _all_ four of the +following criteria + +- header `magic: foo` +- query param `great: example` +- path prefix `/some/thing` +- method `GET` + +to service "my-service2" on port `8080`: +```yaml +{% include 'standard/basic-http.yaml' %} +``` + +The following example uses the `weight` field to forward 90% of HTTP requests to +`foo.example.com` to the "foo-v1" Service and the other 10% to the "foo-v2" +Service: +```yaml +{% include 'standard/traffic-splitting/traffic-split-2.yaml' %} +``` + +Reference the [backendRef][backendRef] API documentation for additional details +on `weight` and other fields. + +#### Timeouts (optional) + +??? example "Experimental Channel since v1.0.0" + + HTTPRoute timeouts have been part of the Experimental Channel since `v1.0.0`. + For more information on release channels, refer to our + [versioning guide](../concepts/versioning.md). + +HTTPRoute Rules include a `Timeouts` field. If unspecified, timeout behavior is implementation-specific. + +There are 2 kinds of timeouts that can be configured in an HTTPRoute Rule: + +1. `request` is the timeout for the Gateway API implementation to send a response to a client HTTP request. This timeout is intended to cover as close to the whole request-response transaction as possible, although an implementation MAY choose to start the timeout after the entire request stream has been received instead of immediately after the transaction is initiated by the client. + +2. `backendRequest` is a timeout for a single request from the Gateway to a backend. This timeout covers the time from when the request first starts being sent from the gateway to when the full response has been received from the backend. This can be particularly helpful if the Gateway retries connections to a backend. + +Because the `request` timeout encompasses the `backendRequest` timeout, the value of `backendRequest` must not be greater than the value of `request` timeout. + +Timeouts are optional, and their fields are of type [Duration](../geps/gep-2257/index.md). A zero-valued timeout ("0s") MUST be interpreted as disabling the timeout. A valid non-zero-valued timeout MUST be >= 1ms. + +The following example uses the `request` field which will cause a timeout if a client request is taking longer than 10 seconds to complete. The example also defines a 2s `backendRequest` which specifies a timeout for an individual request from the gateway to a backend service `timeout-svc`: + +```yaml +{% include 'experimental/http-route-timeouts/timeout-example.yaml' %} +``` + +Reference the [timeouts][timeouts] API documentation for additional details. + +#### Name (optional) + +??? example "Experimental Channel since v1.2.0" + + This concept has been part of the Experimental Channel since `v1.2.0`. + For more information on release channels, refer to our + [versioning guide](../concepts/versioning.md). + +HTTPRoute Rules include an optional `name` field. The applications for the name of a route rule are implementation-specific. It can be used to reference individual route rules by name from other resources, such as in the `sectionName` field of metaresources ([GEP-2648](../geps/gep-2648/index.md#section-names)), in the status stanzas of resources related to the route object, to identify internal configuration objects generated by the implementation from HTTPRoute Rule, etc. + +If specified, the value of the name field must comply with the [`SectionName`](https://github.com/kubernetes-sigs/gateway-api/blob/v1.0.0/apis/v1/shared_types.go#L607-L624) type. + +The following example specifies the `name` field to identify HTTPRoute Rules used to split traffic between a _read-only_ backend service and a _write-only_ one: + +```yaml +{% include 'experimental/http-route-rule-name.yaml' %} +``` + +##### Backend Protocol + +??? example "Experimental Channel since v1.0.0" + + This concept has been part of the Experimental Channel since `v1.0.0`. + For more information on release channels, refer to our + [versioning guide](../concepts/versioning.md). + +Some implementations may require the [backendRef][backendRef] to be labeled +explicitly in order to route traffic using a certain protocol. For Kubernetes +Service backends this can be done by specifying the [`appProtocol`][appProtocol] +field. + + +## Status + +Status defines the observed state of HTTPRoute. + +### RouteStatus + +RouteStatus defines the observed state that is required across all route types. + +#### Parents + +Parents define a list of the Gateways (or other parent resources) that are +associated with the HTTPRoute, and the status of the HTTPRoute with respect to +each of these Gateways. When a HTTPRoute adds a reference to a Gateway in +parentRefs, the controller that manages the Gateway should add an entry to this +list when the controller first sees the route and should update the entry as +appropriate when the route is modified. + +The following example indicates HTTPRoute "http-example" has been accepted by +Gateway "gw-example" in namespace "gw-example-ns": +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-example +... +status: + parents: + - parentRef: + name: gw-example + namespace: gw-example-ns + conditions: + - type: Accepted + status: "True" +``` + +## Merging +Multiple HTTPRoutes can be attached to a single Gateway resource. Importantly, +only one Route rule may match each request. For more information on how conflict +resolution applies to merging, refer to the [API specification][httprouterule]. + + +[httproute]: ../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRoute +[httprouterule]: ../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteRule +[hostname]: ../reference/spec.md#gateway.networking.k8s.io/v1.Hostname +[rfc-3986]: https://tools.ietf.org/html/rfc3986 +[matches]: ../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteMatch +[filters]: ../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteFilter +[backendRef]: ../reference/spec.md#gateway.networking.k8s.io/v1.HTTPBackendRef +[parentRef]: ../reference/spec.md#gateway.networking.k8s.io/v1.ParentRef +[timeouts]: ../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteTimeouts +[appProtocol]: https://kubernetes.io/docs/concepts/services-networking/service/#application-protocol +[sectionName]: ../reference/spec.md#gateway.networking.k8s.io/v1.SectionName diff --git a/site-src/ko/api-types/referencegrant.md b/site-src/ko/api-types/referencegrant.md new file mode 100644 index 0000000000..9ac9964a0f --- /dev/null +++ b/site-src/ko/api-types/referencegrant.md @@ -0,0 +1,160 @@ +# ReferenceGrant + +??? success "Standard Channel since v0.6.0" + + The `ReferenceGrant` resource is Beta and part of the + Standard Channel since `v0.6.0`. For more information on release + channels, refer to our [versioning guide](../concepts/versioning.md). + +!!! note + This resource was originally named "ReferencePolicy". It was renamed + to "ReferenceGrant" to avoid any confusion with policy attachment. + +A ReferenceGrant can be used to enable cross namespace references within +Gateway API. In particular, Routes may forward traffic to backends in other +namespaces, or Gateways may refer to Secrets in another namespace. + +![Reference Grant](../images/referencegrant-simple.svg) + + +In the past, we've seen that forwarding traffic across namespace boundaries is a +desired feature, but without a safeguard like ReferenceGrant, +[vulnerabilities](https://github.com/kubernetes/kubernetes/issues/103675) can +emerge. + +If an object is referred to from outside its namespace, the object's owner must +create a ReferenceGrant resource to explicitly allow that reference. Without a +ReferenceGrant, a cross namespace reference is invalid. + +## Structure +Fundamentally a ReferenceGrant is made up of two lists, a list of resources +references may come from, and a list of resources that may be referenced. + +The `from` list allows you to specify the group, kind, and namespace of +resources that may reference items described in the `to` list. + +The `to` list allows you to specify the group and kind of resources that may be +referenced by items described in the `from` list. The namespace is not necessary +in the `to` list because a ReferenceGrant can only be used to allow references +to resources in the same namespace as the ReferenceGrant. + +## Example +The following example shows how a HTTPRoute in namespace `foo` can reference a +Service in namespace `bar`. In this example a ReferenceGrant in the `bar` +namespace explicitly allows references to Services from HTTPRoutes in the `foo` +namespace. + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: foo + namespace: foo +spec: + rules: + - matches: + - path: /bar + backendRefs: + - name: bar + namespace: bar +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: ReferenceGrant +metadata: + name: bar + namespace: bar +spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: foo + to: + - group: "" + kind: Service +``` + +## API design decisions +While the API is simplistic in nature, it comes with a few notable decisions: + +1. Each ReferenceGrant only supports a single From and To section. Additional + trust relationships must be modeled with additional ReferenceGrant + resources. +1. Resource names are intentionally excluded from the "From" section of + ReferenceGrant because they rarely provide any meaningful protection. A user + that is able to write to resources of a certain kind within a namespace can + always rename resources or change the structure of the resources to match a + given grant. +1. A single Namespace is allowed per "From" struct. Although a selector would be + more powerful, it encourages unnecessarily insecure configuration. +1. The effect of these resources is purely additive, they stack on top of each + other. This makes it impossible for them to conflict with each other. + +Please see the [API +Specification](../reference/spec.md#gateway.networking.k8s.io/v1alpha2.ReferenceGrant) +for more details on how specific ReferenceGrant fields are interpreted. + +## Implementation Guidelines +This API relies on runtime verification. Implementations MUST watch for changes +to these resources and recalculate the validity of cross-namespace references +after each change or deletion. + +When communicating the status of a cross-namespace reference, implementations +MUST NOT expose information about the existence of a resource in another +namespace unless a ReferenceGrant exists allowing the reference to occur. This +means that if a cross-namespace reference is made without a ReferenceGrant to a +resource that doesn't exist, any status conditions or warning messages need to +focus on the fact that a ReferenceGrant does not exist to allow this reference. +No hints should be provided about whether or not the referenced resource exists. + +## Exceptions +Cross namespace Route -> Gateway binding follows a slightly different pattern +where the handshake mechanism is built into the Gateway resource. For more +information on that approach, refer to the relevant [Security Model +documentation](../concepts/security-model.md). Although conceptually similar to +ReferenceGrant, this configuration is built directly into Gateway Listeners, +and allows for fine-grained per Listener configuration that would not be +possible with ReferenceGrant. + +There are some situations where it MAY be acceptable to ignore ReferenceGrant +in favor of some other security mechanism. This MAY only be done if other +mechanisms like NetworkPolicy can effectively limit cross-namespace references +by the implementation. + +An implementation choosing to make this exception MUST clearly document that +ReferenceGrant is not honored by their implementations and detail which +alternative safeguards are available. Note that this is unlikely to apply to +ingress implementations of the API and will not apply to all mesh +implementations. + +For an example of the risks involved in cross-namespace references, refer to +[CVE-2021-25740](https://github.com/kubernetes/kubernetes/issues/103675). +Implementations of this API need to be very careful to avoid confused deputy +attacks. ReferenceGrant provides a safeguard for that. Exceptions MUST only be +made by implementations that are absolutely certain that other equally effective +safeguards are in place. + +## Conformance Level +ReferenceGrant support is a "CORE" conformance level requirement for +cross-namespace references that originate from the following objects: + +- Gateway +- GRPCRoute +- HTTPRoute +- TLSRoute +- TCPRoute +- UDPRoute + +That is, all implementations MUST use this flow for any cross namespace +references in the Gateway and any of the core xRoute types, except as noted +in the Exceptions section above. + +Other "ImplementationSpecific" objects and references MUST also use this flow +for cross-namespace references, except as noted in the Exceptions section above. + +## Potential Future API Group Change + +ReferenceGrant is starting to gain interest outside of Gateway API and SIG +Network use cases. It is possible that this resource may move to a more neutral +home. Users of the ReferenceGrant API may be required to transition to a +different API Group (instead of `gateway.networking.k8s.io`) at some point in +the future. diff --git a/site-src/ko/blog/2021/introducing-v1alpha2.md b/site-src/ko/blog/2021/introducing-v1alpha2.md new file mode 100644 index 0000000000..55f5231efa --- /dev/null +++ b/site-src/ko/blog/2021/introducing-v1alpha2.md @@ -0,0 +1,149 @@ +--- +description: > + We’re pleased to announce the release of v1alpha2, our second alpha API + version. This release includes some major changes and improvements. This post + will cover the highlights. +--- + +# Introducing Gateway API v1alpha2 + + + :octicons-calendar-24: October 14, 2021 · + :octicons-clock-24: 5 min read + + +We’re pleased to announce the release of v1alpha2, our second alpha API version. +This release includes some major changes and improvements. This post will cover +the highlights. + +## Highlights + +### New API Group +To recognize our status as an official Kubernetes API, we've transitioned from +an experimental API group (`networking.x-k8s.io`) to the new +`gateway.networking.k8s.io` API group. This means that, as far as the apiserver +is concerned, this version is wholly distinct from v1alpha1, and automatic +conversion is not possible. + +![New API group for v1alpha2](../../images/v1alpha2-group.png) + +### Simpler Route-Gateway Binding +In v1alpha1 we provided many ways to connect Gateways and Routes. This was a bit +more complicated to understand than we'd like. With v1alpha2, we've focused on +simpler attachment mechanism: + +* Routes directly reference the Gateway(s) they want to attach to. This is a + list, so a Route can attach to more than one Gateway. +* Each Gateway listener can choose to specify the kinds of Routes they support + and where they can be. This defaults to Routes that support the specified + protocol in the same Namespace as the Gateway. + +For example, the following HTTPRoute uses the `parentRefs` field to attach +itself to the `prod-web-gw` Gateway. + +```yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: foo +spec: + parentRefs: + - name: prod-web + rules: + - backendRefs: + - name: foo-svc + port: 8080 +``` + +This is covered in more detail in [GEP 724](../../geps/gep-709/index.md). + +### Safe Cross Namespace References + +!!! info "Experimental Channel" + + The `ReferenceGrant` resource described below is currently only included in the + "Experimental" channel of Gateway API. For more information on release + channels, refer to our [versioning guide](../../concepts/versioning.md). + +It is quite challenging to cross namespace boundaries in a safe manner. With +Gateway API, we had several key feature requests that required this capability. +Most notably, forwarding traffic to backends in other namespaces and referring +to TLS certificates in other namespaces. + +To accomplish this, we've introduced a new ReferenceGrant resource that +provides a handshake mechanism. By default, references across namespaces are not +permitted; creating a reference across a namespace (like a Route referencing a +Service in another namespace) must be rejected by implementations. These +references can be accepted by creating a ReferenceGrant in the referent +(target) namespace, that specifies what Kind is allowed to accept incoming +references, and from what namespace and Kind the references may be. + +For example, the following ReferenceGrant would allow HTTPRoutes in the prod +namespace to forward traffic to Services wherever this ReferenceGrant was +installed: + +```yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: ReferenceGrant +metadata: + name: allow-prod-traffic +spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: prod + to: + - group: "" + kind: Service +``` + +This is covered in more detail in [GEP 709](../../geps/gep-709/index.md). + +### Policy Attachment +One of the key goals of this API is to provide meaningful and consistent +extension points. In v1alpha2, we've introduced a new standard for attaching +policies to Gateway API resources. + +What is a policy? Well, it's kind of up to the implementations, but the best +example to begin with is timeout policy. + +Timeout policy for HTTP connections is highly dependent on how the underlying +implementation handles policy - it's very difficult to extract commonalities. + +This is intended to allow things like: + +* Attaching a policy that specifies the default connection timeout for backends + to a GatewayClass. All Gateways that are part of that Class will have Routes + get that default connection timeout unless they specify differently. +* If a Gateway that's a member of the GatewayClass has a different default + attached, then that will beat the GatewayClass (for defaults, more specific + object beats less specific object). +* Alternatively, a Policy that mandates that you can't set the client timeout to + "no timeout" can be attached to a GatewayClass as an override. An override + will always take effect, with less specific beating more specific. + +As a simple example, a TimeoutPolicy may be attached to a Gateway. The effects +of that policy would cascade down to Routes attached to that policy: + +![Simple Ingress Example](../../images/policy/ingress-simple.png) + +This is covered in more detail in [GEP 713](../../geps/gep-713/index.md). + +## Next Steps +There are a lot of changes in v1alpha2 that we haven't covered here. For the +full changelog, refer to our [v0.4.0 release +notes](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v0.4.0). + +Many of our [implementations](../../implementations.md) are planning to release support +for the v1alpha2 API in the coming weeks. We'll update our documentation as +v1alpha2 implementations become available. + +We still have lots more to work on. Some of our next items to discuss include: + +* Conformance testing +* Route delegation +* Rewrite support +* L4 Route matching + +If these kinds of topics interest you, we'd love to have your input. Refer to +our [community page](../../contributing/index.md) to see how you can get involved. diff --git a/site-src/ko/blog/2022/graduating-to-beta.md b/site-src/ko/blog/2022/graduating-to-beta.md new file mode 100644 index 0000000000..7b0e011560 --- /dev/null +++ b/site-src/ko/blog/2022/graduating-to-beta.md @@ -0,0 +1,184 @@ +--- +description: > + We are excited to announce the v0.5.0 release of Gateway API. For the first + time, several of our most important Gateway API resources are graduating to + beta. Additional, we are starting a new initiative to explore how Gateway API + can be used for mesh and introducing new experimental concepts such as URL + rewrites. +--- + +# Gateway API Graduates to Beta + + + :octicons-calendar-24: July 13, 2022 · + :octicons-clock-24: 5 min read + + +We are excited to announce the v0.5.0 release of Gateway API. For the first +time, several of our most important Gateway API resources are graduating to +beta. Additionally, we are starting a new initiative to explore how Gateway API +can be used for mesh and introducing new experimental concepts such as URL +rewrites. We'll cover all of this and more below. + +## What is Gateway API? + +Gateway API is a collection of resources centered around [Gateway][gw] resources +(which represent the underlying network gateways / proxy servers) to enable +robust Kubernetes service networking through expressive, extensible and +role-oriented interfaces that are implemented by many vendors and have broad +industry support. + +Originally conceived as a successor to the well known [Ingress][ing] API, the +benefits of Gateway API include (but are not limited to) explicit support for +many commonly used networking protocols (e.g. `HTTP`, `TLS`, `TCP`, `UDP`) as +well as tightly integrated support for Transport Layer Security (TLS). The +`Gateway` resource in particular enables implementations to manage the lifecycle +of network gateways as a Kubernetes API. + +If you're an end-user interested in some of the benefits of Gateway API we +invite you to jump in and find an implementation that suits you. At the time of +this release there are over a dozen [implementations][impl] for popular API +gateways and service meshes and guides are available to start exploring quickly. + +[gw]:../../api-types/gateway.md +[ing]:https://kubernetes.io/docs/reference/kubernetes-api/service-resources/ingress-v1/ +[impl]:../../implementations.md + +### Getting started + +Gateway API is an official Kubernetes API like +[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/). +Gateway API represents a superset of Ingress functionality, enabling more +advanced concepts. Similar to Ingress, there is no default implementation of +Gateway API built into Kubernetes. Instead, there are many different +[implementations][impl] available, providing significant choice in terms of underlying +technologies while providing a consistent and portable experience. + +Take a look at the [API concepts documentation][concepts] and check out some of +the [Guides][guides] to start familiarizing yourself with the APIs and how they +work. When you're ready for a practical application open the [implementations +page][impl] and select an implementation that belongs to an existing technology +you may already be familiar with or the one your cluster provider uses as a +default (if applicable). Gateway API is a [Custom Resource Definition +(CRD)][crd] based API so you'll need to [install the CRDs][install-crds] onto a +cluster to use the API. + +If you're specifically interested in helping to contribute to Gateway API, we +would love to have you! Please feel free to [open a new issue][issue] on the +repository, or join in the [discussions][disc]. Also check out the [community +page][community] which includes links to the Slack channel and community meetings. + +[crd]:https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/ +[concepts]:../../concepts/api-overview.md +[guides]:../../guides/index.md +[impl]:../../implementations.md +[install-crds]:../../guides/index.md#installing-gateway-api +[issue]:https://github.com/kubernetes-sigs/gateway-api/issues/new/choose +[disc]:https://github.com/kubernetes-sigs/gateway-api/discussions +[community]:../../contributing/index.md + +## Release highlights + +### Graduation to beta + +The `v0.5.0` release is particularly historic because it marks the growth in +maturity to a beta API version (`v1beta1`) release for some of the key APIs: + +- [GatewayClass](../../api-types/gatewayclass.md) +- [Gateway](../../api-types/gateway.md) +- [HTTPRoute](../../api-types/httproute.md) + +This achievement was marked by the completion of several graduation criteria: + +- API has been [widely implemented][impl]. +- Conformance tests provide basic coverage for all resources and have multiple implementations passing tests. +- Most of the API surface is actively being used. +- Kubernetes SIG Network API reviewers have approved graduation to beta. + +For more information on Gateway API versioning, refer to the [official +documentation](../../concepts/versioning.md). To see +what's in store for future releases check out the [next steps](#next-steps) +section. + +[impl]:../../implementations.md + +### Release channels + +This release introduces the `experimental` and `standard` [release channels][ch] +which enable a better balance of maintaining stability while still enabling +experimentation and iterative development. + +The `standard` release channel includes: + +- resources that have graduated to beta +- fields that have graduated to standard (no longer considered experimental) + +The `experimental` release channel includes everything in the `standard` release +channel, plus: + +- `alpha` API resources +- fields that are considered experimental and have not graduated to `standard` channel + +Release channels are used internally to enable iterative development with +quick turnaround, and externally to indicate feature stability to implementors +and end-users. + +For this release we've added the following experimental features: + +- [Routes can attach to Gateways by specifying port numbers](../../geps/gep-957/index.md) +- [URL rewrites and path redirects](../../geps/gep-726/index.md) + +[ch]:../../concepts/versioning.md#release-channels + +### Other improvements + +For an exhaustive list of changes included in the `v0.5.0` release, please see +the [v0.5.0 release notes](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v0.5.0). + +## Gateway API for service mesh: the GAMMA Initiative +Some service mesh projects have [already implemented support for the Gateway +API](../../implementations.md). Significant overlap +between the Service Mesh Interface (SMI) APIs and the Gateway API has [inspired +discussion in the SMI +community](https://github.com/servicemeshinterface/smi-spec/issues/249) about +possible integration. + +We are pleased to announce that the service mesh community, including +representatives from Cilium Service Mesh, Consul, Istio, Kuma, Linkerd, NGINX +Service Mesh and Open Service Mesh, is coming together to form the [GAMMA +Initiative](../../mesh/index.md), a dedicated +workstream within the Gateway API subproject focused on Gateway API for Mesh +Management and Administration. + +This group will deliver [enhancement +proposals](../../contributing/enhancement-requests.md) consisting +of resources, additions, and modifications to the Gateway API specification for +mesh and mesh-adjacent use-cases. + +This work has begun with [an exploration of using Gateway API for +service-to-service +traffic](https://docs.google.com/document/d/1T_DtMQoq2tccLAtJTpo3c0ohjm25vRS35MsestSL9QU/edit#heading=h.jt37re3yi6k5) +and will continue with enhancement in areas such as authentication and +authorization policy. + +## Next steps + +As we continue to mature the API for production use cases, here are some of the highlights of what we'll be working on for the next Gateway API releases: + +- [GRPCRoute][gep1016] for [gRPC][grpc] traffic routing +- [Route delegation][pr1085] +- Layer 4 API maturity: Graduating [TCPRoute][tcpr], [UDPRoute][udpr] and + [TLSRoute][tlsr] to beta +- [GAMMA Initiative](../../mesh/index.md) - Gateway API for Service Mesh + +If there's something on this list you want to get involved in, or there's +something not on this list that you want to advocate for to get on the roadmap +please join us in the #sig-network-gateway-api channel on Kubernetes Slack or our weekly [community calls](../../contributing/index.md#meetings). + +[gep1016]:https://github.com/kubernetes-sigs/gateway-api/blob/master/geps/gep-1016.md +[grpc]:https://grpc.io/ +[pr1085]:https://github.com/kubernetes-sigs/gateway-api/pull/1085 +[tcpr]:https://github.com/kubernetes-sigs/gateway-api/blob/main/apis/v1alpha2/tcproute_types.go +[udpr]:https://github.com/kubernetes-sigs/gateway-api/blob/main/apis/v1alpha2/udproute_types.go +[tlsr]:https://github.com/kubernetes-sigs/gateway-api/blob/main/apis/v1alpha2/tlsroute_types.go +[community]:../../contributing/index.md diff --git a/site-src/ko/blog/2023/0829-mesh-support.md b/site-src/ko/blog/2023/0829-mesh-support.md new file mode 100644 index 0000000000..7bc15c4429 --- /dev/null +++ b/site-src/ko/blog/2023/0829-mesh-support.md @@ -0,0 +1,209 @@ +--- +description: > + We are excited to announce the v0.8.0 release of Gateway API, where service + mesh support has now reached Experimental status, we've introduced CEL + validation and a Mesh conformance profile, and more! +--- + +# Gateway API v0.8.0: Introducing Service Mesh Support! + + + :octicons-calendar-24: August 29, 2023 · + :octicons-clock-24: 5 min read + + +We are thrilled to announce the v0.8.0 release of Gateway API! With this +release, Gateway API support for service mesh has reached [Experimental +status][status], and we've also made some smaller additions such as CEL +validation. We look forward to your feedback! + +We're especially delighted to announce that Kuma 2.3+, Linkerd 2.14+, and +Istio 1.16+ are all fully-conformant implementations of the Gateway API +service mesh support. + +## Service mesh support in Gateway API + +While the initial focus of Gateway API was always ingress (north-south) +traffic, it was clear almost from the beginning that the same basic routing +concepts should also be applicable to service mesh (east-west) traffic. In +2022, the Gateway API subproject started the [GAMMA initiative][gamma], a +dedicated vendor-neutral workstream, specifically to examine how best to fit +service mesh support into the framework of the Gateway API resources, without +requiring users of Gateway API to relearn everything they understand about the +API. + +Over the last year, GAMMA has dug deeply into the challenges and possible +solutions around using the Gateway API for service mesh. The end result is a +small number of [enhancement proposals][geps] that subsume many hours of +thought and debate, and provide a minimum viable path to allow the Gateway API +to be used for service mesh. + +### How will mesh routing work when using the Gateway API? + +You can find all the details in the [Gateway API Mesh routing +documentation][mesh-routing] and [GEP-1426], but the short version for Gateway +API v0.8.0 is that an HTTPRoute can now have a `parentRef` that is a Service, +rather than just a Gateway. We anticipate future GEPs in this area as we gain +more experience with service mesh use cases -- binding to a Service makes it +possible to use the Gateway API with a service mesh, but there are several +interesting use cases that remain difficult to cover. + +As an example, you might use an HTTPRoute to do an A-B test in the mesh as +follows: + +```yaml + apiVersion: gateway.networking.k8s.io/v1beta1 + kind: HTTPRoute + metadata: + name: bar-route + spec: + parentRefs: + - group: "" + kind: Service + name: demo-app + port: 5000 + rules: + - matches: + - headers: + - type: Exact + name: env + value: v1 + backendRefs: + - name: demo-app-v1 + port: 5000 + - backendRefs: + - name: demo-app-v2 + port: 5000 +``` + +Any request to port 5000 of the `demo-app` Service that has the header `env: +v1` will be routed to `demo-app-v1`, while any request without that header +will be routed to `demo-app-v2` -- and since this is being handled by the +service mesh, not the ingress controller, the A/B test can happen anywhere in +the application's call graph. + +### How do I know this will be truly portable? + +Gateway API has been investing heavily in conformance tests across all +features it supports, and mesh is no exception. One of the challenges that the +GAMMA initiative ran into is that many of these tests were strongly tied to +the idea that a given implementation provides an ingress controller. Many +service meshes don't, and requiring a GAMMA-conformant mesh to also implement +an ingress controller seemed impractical at best. This resulted in work +restarting on Gateway API _conformance profiles_, as discussed in [GEP-1709]. + +The basic idea of conformance profiles is that we can define subsets of the +Gateway API, and allow implementations to choose (and document) which subsets +they conform to. GAMMA is adding a new profile, named `Mesh` and described in +[GEP-1686], which checks only the mesh functionality as defined by GAMMA. At +this point, Kuma 2.3+, Linkerd 2.14+, and Istio 1.16+ are all conformant with +the `Mesh` profile. + +## What else is in Gateway API v0.8.0? + +This release is all about preparing Gateway API for the upcoming v1.0 release +where HTTPRoute, Gateway, and GatewayClass will graduate to GA. There are two +main changes related to this: CEL validation and GEP process changes. + +### CEL Validation + +The first major change is that Gateway API v0.8.0 is the start of a transition +from webhook validation to [CEL validation][cel] using information built into +the CRDs. That will mean different things depending on the version of +Kubernetes you're using: + +#### Kubernetes 1.25+ + +CEL validation is fully supported, and almost all validation is implemented in +CEL. (The sole exception is that header names in header modifier filters can +only do case-insensitive validation. There is more information in [issue +2277].) + +We recommend _not_ using the validating webhook on these Kubernetes versions. + +#### Kubernetes 1.23 and 1.24 + +CEL validation is not supported, but Gateway API v0.8.0 CRDs can still be +installed. When you upgrade to Kubernetes 1.25+, the validation included in +these CRDs will automatically take effect. + +We recommend continuing to use the validating webhook on these Kubernetes +versions. + +#### Kubernetes 1.22 and older + +Gateway API only commits to support for [5 most recent versions of +Kubernetes][supported-versions]. As such, these versions are no longer +supported by Gateway API, and unfortunately Gateway API v0.8.0 cannot be +installed on them, since CRDs containing CEL validation will be rejected. + +### GEP Process Changes + +The second significant change in Gateway API v0.8.0 is that we have (by +necessity) taken a hard look at the process around [Experimental][status] +GEPs. Some of these GEPs have been lingering long enough that projects have +come to rely on them in production use, which is a bit of a breakdown of the +GEP process. In order to prevent it happening in the future, we have changed +the GEP process such that reaching [Experimental][status] _requires_ that a +GEP include both the graduation criteria by which the GEP will become +[Standard][status], and a probationary period after which the GEP will be +dropped if does not meet its graduation criteria. + +For an exhaustive list of changes included in the `v0.8.0` release, please see +the [v0.8.0 release notes]. For more information on Gateway API versioning, +refer to the [official documentation][versioning docs]. + +## How can I get started with the Gateway API? + +Gateway API represents the future of load balancing, routing, and service mesh +APIs in Kubernetes. There are already more than 20 [implementations][impl] +available (including both ingress controllers and service meshes) and the list +keeps growing. + +If you're interested in getting started with Gateway API, take a look at the +[API concepts documentation][concepts] and check out some of the +[Guides][guides] to try it out. Because this is a CRD-based API, you can +install the latest version on any Kubernetes 1.23+ cluster. + +If you're specifically interested in helping to contribute to Gateway API, we +would love to have you! Please feel free to [open a new issue][issue] on the +repository, or join in the [discussions][disc]. Also check out the [community +page][community] which includes links to the Slack channel and community +meetings. We look forward to seeing you!! + +## Further Reading: + +- [GEP-1324] provides an overview of the GAMMA goals and some important + definitions. This GEP is well worth a read for its discussion of the problem + space. +- [GEP-1426] defines how to use Gateway API route resources, such as + HTTPRoute, to manage traffic within a service mesh. +- [GEP-1686] builds on the work of [GEP-1709] to define a _conformance + profile_ for service meshes to be declared conformant with the Gateway API. + +Although these are [Experimental][status] patterns, note that they are +available in the [`standard` release channel][ch], since the GAMMA initiative +has not needed to introduce new resources or fields to date. + +[gamma]:../../mesh/index.md +[status]:../../geps/overview.md#gep-states +[ch]:../../concepts/versioning.md#release-channels +[cel]:https://kubernetes.io/docs/reference/using-api/cel/ +[crd]:https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/ +[concepts]:../../concepts/api-overview.md +[geps]:../../contributing/enhancement-requests.md +[guides]:../../guides/index.md +[impl]:../../implementations.md +[install-crds]:../../guides/index.md#installing-gateway-api +[issue]:https://github.com/kubernetes-sigs/gateway-api/issues/new/choose +[disc]:https://github.com/kubernetes-sigs/gateway-api/discussions +[community]:../../contributing/index.md +[mesh-routing]:../../mesh/index.md +[GEP-1426]:../../geps/gep-1294/index.md +[GEP-1324]:../../geps/gep-1324/index.md +[GEP-1686]:../../geps/gep-1686/index.md +[GEP-1709]:../../geps/gep-1709/index.md +[issue 2277]:https://github.com/kubernetes-sigs/gateway-api/issues/2277 +[supported-versions]:../../concepts/versioning.md#supported-versions +[v0.8.0 release notes]:https://github.com/kubernetes-sigs/gateway-api/releases/tag/v0.8.0 +[versioning docs]:../../concepts/versioning.md diff --git a/site-src/ko/blog/index.md b/site-src/ko/blog/index.md new file mode 100644 index 0000000000..85027e3d40 --- /dev/null +++ b/site-src/ko/blog/index.md @@ -0,0 +1,53 @@ +# Blog + + + +## [Gateway API: Introducing Service Mesh Support!] + + + :octicons-calendar-24: August 29, 2023 · + :octicons-clock-24: 5 min read + + +We are thrilled to announce the v0.8.0 release of Gateway API! With this +release, Gateway API support for service mesh has reached [Experimental +status][status], we've introduced CEL validation and a `Mesh` conformance +profile, and we've made some changes to the GEP process. We look forward to +your feedback! + +[:octicons-arrow-right-24: Continue reading][Gateway API: Introducing Service Mesh Support!] + +[status]:../geps/overview.md#gep-states +[Gateway API: Introducing Service Mesh Support!]:2023/0829-mesh-support.md + +## [Gateway API Graduates to Beta] + + + :octicons-calendar-24: July 13, 2022 · + :octicons-clock-24: 5 min read + + +We are excited to announce the v0.5.0 release of Gateway API. For the first +time, several of our most important Gateway API resources are graduating to +beta. Additionally, we are starting a new initiative to explore how Gateway API +can be used for mesh and introducing new experimental concepts such as URL +rewrites. + +[:octicons-arrow-right-24: Continue reading][Gateway API Graduates to Beta] + +[Gateway API Graduates to Beta]:2022/graduating-to-beta.md + +## [Introducing Gateway API v1alpha2] + + + :octicons-calendar-24: October 14, 2021 · + :octicons-clock-24: 5 min read + + +We’re pleased to announce the release of v1alpha2, our second alpha API version. +This release includes some major changes and improvements. This post will cover +the highlights. + +[:octicons-arrow-right-24: Continue reading][Introducing Gateway API v1alpha2] + +[Introducing Gateway API v1alpha2]: 2021/introducing-v1alpha2.md diff --git a/site-src/ko/concepts/api-overview.md b/site-src/ko/concepts/api-overview.md new file mode 100644 index 0000000000..b61eafe25f --- /dev/null +++ b/site-src/ko/concepts/api-overview.md @@ -0,0 +1,355 @@ +# API 개요 + +이 문서는 게이트웨이 API에 대한 개요를 제공한다. + +## 역할과 페르소나 + +[역할과 페르소나]에 설명된 대로 게이트웨이 API에는 3가지 주요 역할이 있다. + +- **Ian** (그/그의): 인프라 제공자 +- **Chihiro** (그들/그들의): 클러스터 운영자 +- **Ana** (그녀/그녀의): 애플리케이션 개발자 + +[역할과 페르소나]:roles-and-personas.md + +## 리소스 모델 + +!!! 참고 + 게이트웨이 API 리소스는 커스텀 리소스 정의(CRDs)로서 + `gateway.networking.k8s.io` API 그룹에 속해 있다. + 아래의 리소스 이름은 특별한 언급이 없는 한 이 API 그룹에 속한 것으로 간주된다. + +리소스 모델에는 세 가지 주요 객체 타입이 있다. + +*Gateway Class*는 공통 구성과 동작을 가진 게이트웨이 집합을 +정의한다. + +*Gateway*는 트래픽이 클러스터 내의 서비스로 변환될 수 있는 지점을 +요청한다. + +*Route*는 게이트웨이를 통해 들어오는 트래픽이 서비스에 어떻게 매핑되는지 설명한다. + +### 게이트웨이 클래스 (GatewayClass) + +??? success "v0.5.0 부터 표준 채널" + + `GatewayClass` 리소스는 GA(정식 출시)되었으며 `v0.5.0` 부터 표준 채널의 일부이다. + 릴리스 채널에 대한 자세한 정보는 + [버전 관리 가이드](versioning.md)를 참조하자. + +게이트웨이 클래스는 공통 구성과 동작을 공유하는 게이트웨이 집합을 정의한다. +각 게이트웨이 클래스는 단일 컨트롤러에 의해 처리되지만, +컨트롤러는 여러 게이트웨이 클래스를 처리할 수 있다. + +게이트웨이 클래스는 클러스터 범위의 리소스이다. +기능적인 게이트웨이를 사용하기 위해서는 최소한 하나의 게이트웨이 클래스가 정의되어 있어야 한다. +게이트웨이 API를 구현하는 컨트롤러는 사용자가 게이트웨이에서 참조할 수 있는 연관된 +게이트웨이 클래스 리소스를 제공함으로써 이를 수행한다. + +이는 인그레스의 +[인그레스 클래스](https://kubernetes.io/ko/docs/concepts/services-networking/ingress/#%EC%9D%B8%EA%B7%B8%EB%A0%88%EC%8A%A4-%ED%81%B4%EB%9E%98%EC%8A%A4)와 +퍼시스턴트 볼륨의 +[스토리지 클래스](https://kubernetes.io/ko/docs/concepts/storage/storage-classes/)와 유사하다. +인그레스 v1beta1에서 게이트웨이 클래스와 +가장 유사한 것은 `ingress-class` 어노테이션이며, +IngressV1에서는 인그레스 클래스 객체가 가장 유사하다. + +### 게이트웨이 (Gateway) + +??? success "v0.5.0 부터 표준 채널" + + `게이트웨이` 리소스는 GA(정식 출시)되었으며 `v0.5.0` 부터 표준 채널의 일부이다. + 릴리스 채널에 대한 자세한 정보는 [버전 관리 가이드](versioning.md)를 + 참조하자. + +게이트웨이는 트래픽이 클러스터 내의 서비스로 어떻게 변환될 수 있는지 설명한다. +즉, 쿠버네티스를 알지 못하는 곳에서 +쿠버네티스를 아는 곳으로 트래픽을 변환하는 방법에 대한 요청을 정의한다. +예를 들어, 클라우드 로드 밸런서, 클러스터 내 프록시 또는 외부 하드웨어 로드 밸런서에 의해 +쿠버네티스 서비스로 전송되는 트래픽이 이에 해당한다. +많은 사용 사례에서 클라이언트 트래픽이 클러스터 "외부"에서 시작되지만, +이는 필수 요구사항은 아니다. + +게이트웨이는 게이트웨이 클래스의 구성 및 동작 계약을 구현하는 +특정 로드 밸런서 구성에 대한 요청을 정의한다. +이 리소스는 운영자가 직접 생성하거나, +게이트웨이 클래스를 처리하는 컨트롤러에 의해 생성될 수 있다. + +게이트웨이 스펙은 사용자의 의도를 담고 있으므로, 스펙의 모든 속성에 대한 +완전한 명세를 포함하지 않을 수 있다. +예를 들어, 사용자는 주소, TLS 설정과 같은 필드를 생략할 수 있다. +이를 통해 게이트웨이 클래스를 관리하는 컨트롤러가 +사용자를 위해 이러한 설정을 제공할 수 있으며, 이는 더 이식성 있는 스펙을 제공한다. +이러한 동작은 게이트웨이 클래스 상태 객체를 사용하여 명확하게 표시된다. + +게이트웨이는 하나 이상의 *라우트 참조*에 연결될 수 있으며, +이는 트래픽의 일부를 *특정 서비스*로 전달하는 역할을 한다. + +### 라우트 리소스 (Route Resource) + +라우트 리소스는 게이트웨이에서 쿠버네티스 서비스로의 요청 매핑을 위한 +프로토콜별 규칙을 정의한다. + +v1alpha2를 기준으로, API에는 네 가지 라우트 리소스 타입이 포함되어 있다. +구현별로 특정한 사용자 정의 라우트 타입은 다른 프로토콜에 대해 권장된다. +향후 API에 새로운 라우트 타입이 추가될 수 있다. + +#### HTTPRoute + +??? success "v0.5.0 부터 표준 채널" + + `HTTPRoute` 리소스는 GA(정식 출시)되었으며 `v0.5.0` 부터 표준 채널의 일부이다. + 릴리스 채널에 대한 자세한 정보는 [버전 관리 가이드](versioning.md)를 + 참조하자. + +HTTPRoute는 HTTP 또는 종료된 HTTPS 연결을 다중화하기 위한 것이다. +HTTP 스트림을 검사하고 HTTP 요청 데이터를 라우팅하거나 수정에 사용하려는 경우에 사용된다. +예를 들어, HTTP 헤더를 사용하여 라우팅하거나 +이를 전송 중에 수정하는 경우에 사용된다. + +#### TLSRoute + +??? example "v0.3.0 부터 실험적 채널" + + `TLSRoute` 리소스는 알파 상태이며 `v0.3.0` 부터 실험적 채널의 일부이다. + 릴리스 채널에 대한 자세한 정보는 [버전 관리 가이드](versioning.md)를 + 참조하자. + +TLSRoute는 SNI를 통해 구분되는 TLS 연결을 멀티플렉싱하기 위한 것이다. +SNI를 주요 라우팅 방법으로 사용하고 싶고, HTTP와 같은 상위 레벨 프로토콜의 +속성에는 관심이 없는 경우에 사용된다. 연결의 바이트 스트림은 +백엔드로 검사 없이 프록시된다. + +#### TCPRoute와 UDPRoute + +??? example "v0.3.0 부터 실험적 채널" + + `TCPRoute` 및 `UDPRoute` 리소스는 알파 상태이며 `v0.3.0` 부터 실험적 채널의 일부이다. + 릴리스 채널에 대한 자세한 정보는 [버전 관리 가이드](versioning.md)를 + 참조하자. + +TCPRoute(및 UDPRoute)는 하나 이상의 포트를 단일 백엔드에 매핑하는 데 사용된다. +이 경우, 동일한 포트에서 서로 다른 백엔드를 선택할 수 있는 구분자가 없으므로, +일반적으로 각 TCPRoute는 리스너에서 서로 다른 포트를 필요로 한다. +TLS를 종료할 수 있는데, +이 경우 암호화되지 않은 바이트 스트림이 백엔드에 전달된다. +TLS를 종료하지 않도록 선택할 수도 있으며, +이 경우에는 암호화된 바이트 스트림이 백엔드에 전달된다. + +#### GRPCRoute + +??? success "v1.1.0 부터 표준 채널" + + `GRPCRoute` 리소스는 GA(정식 출시)되었으며 `v1.1.0` 부터 표준 채널의 일부이다. + 릴리스 채널에 대한 자세한 정보는 [버전 관리 가이드](versioning.md)를 + 참조하자. + +GRPCRoute는 gRPC 트래픽을 관용적으로 라우팅하기 위한 것이다. +GRPCRoute를 지원하는 게이트웨이는 HTTP/1에서 초기 업그레이드 없이 +HTTP/2를 지원해야 하므로, gRPC 트래픽이 올바르게 흐를 수 있도록 보장된다. + +#### 라우트 요약 표 + +아래의 "라우팅 식별자" 열은 여러 라우트가 리스너의 포트를 공유할 수 있도록 +하는 데 사용할 수 있는 정보를 나타낸다. + +|객체|OSI 계층|라우팅 식별자|TLS 지원|목적| +|------|---------|---------------------|-----------|-------| +|HTTPRoute| 레이어 7 | HTTP 프로토콜의 모든 것 | 종료만 가능 | HTTP 및 HTTPS 라우팅| +|TLSRoute| 레이어 4와 7 사이 | SNI 또는 다른 TLS 속성 | 패스스루 또는 종료 | HTTP 스트림 검사가 필요하지 않은 HTTPS를 포함한 TLS 프로토콜 라우팅| +|TCPRoute| 레이어 4 | 목적지 포트 | 패스스루 또는 종료 | 리스너에서 백엔드로 TCP 스트림 전달 허용 | +|UDPRoute| 레이어 4 | 목적지 포트 | 없음 | 리스너에서 백엔드로 UDP 스트림 전달 허용 | +|GRPCRoute| 레이어 7 | gRPC 프로토콜의 모든 것 | 종료만 가능 | HTTP/2 및 HTTP/2 클리어텍스트를 통한 gRPC 라우팅| + +참고로 HTTPRoute 및 TCPRoute를 통해 라우팅되는 트래픽은 게이트웨이와 +백엔드 사이에서 암호화될 수 있다(일반적으로 재암호화라고 함). +기존 게이트웨이 API 리소스로는 이를 구성할 수 없지만, +게이트웨이 API에서 표준화된 방식이 정의될 때까지 +구현체에서 이에 대한 사용자 정의 구성을 제공할 수 있다. + +## 라우트를 게이트웨이에 연결하기 + +라우트가 게이트웨이에 연결되면, 이는 기본 로드 밸런서나 프록시를 구성하는 +게이트웨이에 적용되는 구성을 나타낸다. 라우트가 게이트웨이에 연결되는 방법과 +어떤 라우트가 연결되는지는 리소스 자체에 의해 제어된다. 라우트와 +게이트웨이 리소스에는 연결 방법을 허용하거나 제한하는 내장 제어 기능이 있다. +쿠버네티스 RBAC와 함께 이러한 기능은 조직이 라우트가 노출되는 방식과 +어떤 게이트웨이에 노출되는지에 대한 정책을 시행할 수 있게 한다. + +라우트가 게이트웨이에 연결되는 방법에는 다양한 조직 정책과 책임 범위를 +달성하기 위한 많은 유연성이 있다. 게이트웨이와 라우트가 가질 수 있는 +다양한 관계는 다음과 같다. + +- **일대일(One-to-one)** - 게이트웨이와 라우트는 단일 소유자에 의해 + 배포되고 사용되며 일대일 관계를 가질 수 있다. +- **일대다(One-to-many)** - 게이트웨이는 서로 다른 네임스페이스의 + 다양한 팀이 소유한 여러 라우트가 바인딩될 수 있다. +- **다대일(Many-to-one)** - 라우트도 여러 게이트웨이에 바인딩될 수 있어, + 단일 라우트가 서로 다른 IP, 로드 밸런서 또는 네트워크에서 동시에 + 애플리케이션 노출을 제어할 수 있다. + +### 예시 + +[Chihiro]는 `infra` 네임스페이스에 `shared-gw` 게이트웨이를 배포하여 +여러 애플리케이션 팀이 클러스터 외부에 애플리케이션을 노출할 수 있도록 했다. +A팀과 B팀(각각 네임스페이스 `A`와 `B`에 있음)은 자신의 라우트를 +이 게이트웨이에 연결한다. +이들은 서로에 대해 알지 못하며, +라우트 규칙이 서로 충돌하지 않는 한 계속 독립적으로 운영할 수 있다. +C팀은 특별한 네트워킹 요구 사항(성능, 보안 또는 중요도 등)이 있어 +애플리케이션을 외부 세계로 프록시하기 위한 전용 게이트웨이가 필요하다. +C팀은 `C` 네임스페이스에 자체 게이트웨이인 `dedicated-gw`를 배포하며, +이는 `C` 네임스페이스의 앱에서만 사용할 수 있다. + + +![route binding](../images/gateway-route-binding.png) + +[Chihiro]:roles-and-personas.md#Chihiro + +### 작동 방식 + +라우트가 게이트웨이에 연결되기 위해서는 다음 사항이 필요하다. + +1. 라우트는 게이트웨이를 참조하는 `parentRefs` 필드에 항목이 있어야 한다. +2. 게이트웨이의 최소 하나의 리스너가 이 연결을 허용해야 한다. + +#### 게이트웨이 참조 + +??? example "실험적 채널" + + 아래에서 설명하는 `Port` 필드는 현재 게이트웨이 API의 "실험적" + 채널에만 포함되어 있다. 릴리스 채널에 대한 자세한 정보는 + [관련 문서](versioning.md#release-channels)를 참조하자. + +라우트는 네임스페이스(라우트와 게이트웨이가 동일한 네임스페이스에 있는 경우 선택 사항)와 +`parentRef`에서 게이트웨이의 이름을 지정하여 게이트웨이를 참조할 수 있다. +기본적으로 라우트는 +게이트웨이의 모든 리스너에 연결되지만, +`parentRef`에서 아래의 필드를 사용하여 선택을 리스너의 하위 집합으로 제한할 수 있다. + +1. **SectionName** `sectionName`이 설정되면, 라우트는 지정된 이름을 가진 + 리스너를 선택한다. +2. **Port** `port`가 설정되면, 라우트는 지정된 포트에서 리스닝하고 + 이 종류의 라우트와 호환되는 프로토콜을 가진 모든 리스너를 선택한다. + +`parentRef`에서 여러 필드가 설정되면, 라우트는 이러한 필드에 지정된 +모든 조건을 충족하는 리스너를 선택한다. 예를 들어, `sectionName`과 `port`가 +모두 설정된 경우, 라우트는 지정된 이름을 가지고 지정된 포트에서 +리스닝하는 리스너를 선택한다. + +#### 라우트 연결 제한 + +각 게이트웨이 리스너는 다음 메커니즘을 사용하여 어떤 라우트를 +연결할 수 있는지 제한할 수 있다. + +1. **Hostname:** 리스너에 `hostname` 필드가 설정되면, `hostnames` 필드를 + 지정하는 연결된 라우트는 최소한 하나의 겹치는 값을 가져야 한다. +2. **Namespaces:** 리스너의 `allowedRoutes.namespaces` 필드는 라우트가 + 연결될 수 있는 위치를 제한하는 데 사용할 수 있다. `namespaces.from` + 필드는 다음 값을 지원한다. + * `Same`은 기본 옵션이다. 이 게이트웨이와 동일한 네임스페이스에 있는 + 라우트만 연결될 수 있다. + * `All`은 모든 네임스페이스의 라우트가 연결될 수 있도록 허용한다. + * `Selector`는 네임스페이스 레이블 셀렉터에 의해 선택된 네임스페이스의 + 하위 집합에서 라우트가 이 게이트웨이에 연결될 수 있음을 의미한다. + `Selector`가 사용될 때, `namespaces.selector` 필드는 레이블 + 셀렉터를 지정하는 데 사용되어야 한다. 이 필드는 `All` 또는 `Same`과 함께 지원되지 않는다. +3. **Kinds:** 리스너의 `allowedRoutes.kinds` 필드를 사용하여 연결될 수 + 있는 라우트의 종류를 제한할 수 있다. + +위의 내용이 지정되지 않은 경우, 게이트웨이 리스너는 리스너 프로토콜을 +지원하는 동일한 네임스페이스에서 연결된 라우트를 신뢰한다. + +#### 추가 게이트웨이 - 라우트 연결 예시 + +아래 `my-route` 라우트는 `gateway-api-example-ns1`의 `foo-gateway`에 +연결하려고 하며 다른 게이트웨이에는 연결되지 않는다. `foo-gateway`가 +다른 네임스페이스에 있다는 점에 유의하자. `foo-gateway`는 +`gateway-api-example-ns2` 네임스페이스의 HTTPRoute에서 연결을 허용해야 한다. + +```yaml +{% include 'standard/http-route-attachment/httproute.yaml' %} +``` + +이 `foo-gateway`는 `my-route` HTTPRoute의 연결을 허용한다. + +```yaml +{% include 'standard/http-route-attachment/gateway-strict.yaml' %} +``` + +더 관대한 예시로, 아래 게이트웨이는 "expose-apps: true" 레이블이 있는 +네임스페이스에서 모든 HTTPRoute 리소스가 연결될 수 있도록 허용한다. + +```yaml +{% include 'standard/http-route-attachment/gateway-namespaces.yaml' %} +``` + +### 결합된 타입 + +`게이트웨이 클래스`, `게이트웨이`, `xRoute` 및 `서비스`의 조합은 +구현 가능한 로드 밸런서를 정의한다. 아래 다이어그램은 +서로 다른 리소스 간의 관계를 보여준다: + + +![schema](../images/schema-uml.svg) + +### 요청 흐름 + +리버스 프록시를 사용하여 구현된 게이트웨이의 일반적인 [북/남] +API 요청 흐름은 다음과 같다. + +1. 클라이언트가 에 요청을 보낸다. +2. DNS가 이름을 `Gateway` 주소로 해석한다. +3. 리버스 프록시가 `Listener`에서 요청을 수신하고 + [Host 헤더](https://tools.ietf.org/html/rfc7230#section-5.4)를 + 사용하여 `HTTPRoute`와 일치시킨다. +4. 선택적으로, 리버스 프록시는 `HTTPRoute`의 `match` 규칙을 기반으로 + 요청 헤더 및/또는 경로 매칭을 수행할 수 있다. +5. 선택적으로, 리버스 프록시는 `HTTPRoute`의 `filter` 규칙을 기반으로 + 요청을 수정(즉, 헤더 추가/제거)할 수 있다. +6. 마지막으로, 리버스 프록시는 `HTTPRoute`의 `backendRefs` 규칙을 기반으로 + 요청을 클러스터 내의 하나 이상의 객체(즉, `Service`)로 전달한다. + +[북/남]:glossary.md#northsouth-traffic + +### TLS 구성 + +TLS는 게이트웨이 리스너에서 구성되며, 네임스페이스 간에 참조될 수 있다. + +TLS에 대한 자세한 내용은 [TLS 세부 정보](../guides/tls.md) 가이드를 참조하자. + +## 라우트를 서비스에 연결하기 + +게이트웨이 API를 사용하여 [서비스 메시](glossary.md#service-mesh)를 구성할 때, +라우트는 서비스에 직접 연결되어 서비스로 향하는 모든 트래픽에 적용되는 +구성을 나타낸다. 어떤 라우트가 주어진 서비스에 연결되는지와 그 방법은 +라우트 자체(쿠버네티스 RBAC와 함께 작동)에 의해 제어되며, +[GAMMA 라우팅 문서]에서 설명되어 있다. + +[GAMMA]:../mesh/index.md +[GAMMA 라우팅 문서]:../mesh/index.md#connecting-routes-and-services +[서비스 메시]:glossary.md#service-mesh + +## 확장 포인트 + +일반적인 목적의 API로는 처리할 수 없는 +많은 사용 사례에 유연성을 제공하기 위해 +API에 여러 확장 포인트가 제공된다. + +다음은 API의 확장 포인트 요약이다. + +- **BackendRefs**: 이 확장 포인트는 코어 쿠버네티스 서비스 리소스 이외의 + 네트워크 엔드포인트로 트래픽을 전달하는 데 사용되어야 한다. + 예를 들어 S3 버킷, Lambda 함수, 파일 서버 등이 있다. +- **HTTPRouteFilter**: HTTPRoute의 이 API 타입은 HTTP 요청의 + 요청/응답 라이프사이클에 연결하는 방법을 제공한다. +- **Custom Routes**: 위의 확장 포인트가 사용 사례에 충분하지 않은 경우, + 구현자는 현재 API에서 지원되지 않는 프로토콜에 대한 커스텀 라우트 리소스를 + 생성할 수 있다. + 커스텀 라우트 타입은 코어 라우트 타입과 동일한 필드를 공유해야 한다. + 이러한 필드는 CommonRouteSpec과 RouteStatus 내에 포함되어 있다. + +이전 사례 없이 확장 포인트를 사용하는 경우, 커뮤니티에 알려주자. +확장 포인트의 사용에 대해 더 많이 배우면서, +공통 분모를 찾고 +기능을 코어/확장 API 호환성으로 승격시키고자 한다. diff --git a/site-src/ko/concepts/conformance.md b/site-src/ko/concepts/conformance.md new file mode 100644 index 0000000000..951b7aefd0 --- /dev/null +++ b/site-src/ko/concepts/conformance.md @@ -0,0 +1,220 @@ +# 호환성 + +이 API는 광범위한 기능과 사용 사례를 다루며 널리 구현되었다. +이러한 큰 기능 세트와 다양한 구현의 조합은 +API가 사용되는 곳마다 일관된 경험을 제공하기 위해 +명확한 호환성 정의와 테스트를 필요로 한다. + +Gateway API 호환성을 고려할 때 세 가지 중요한 개념이 있다. + +## 1. 릴리스 채널 + +Gateway API 내에서 릴리스 채널은 필드나 리소스의 안정성을 나타내는 데 사용된다. +API의 "standard" 채널에는 "beta"로 졸업한 필드와 리소스가 포함된다. +API의 "experimental" 채널에는 "standard" 채널의 모든 것과 함께 +여전히 중대한 방식으로 변경되거나 **완전히 제거될 수 있는** 실험적인 필드와 +리소스가 포함된다. +이 개념에 대한 자세한 내용은 +[버전 관리](versioning.md) 문서를 참조하자. + +## 2. 지원 수준 + +불행히도 API의 일부 구현은 정의된 모든 기능을 지원할 수 없을 것이다. +이를 해결하기 위해 +API는 각 기능에 대한 해당 지원 수준을 정의한다. + +* **Core** 기능은 이식 가능하며 이 범주의 API 지원을 위한 모든 구현에 대해 + 합리적인 로드맵이 있을 것으로 기대한다. +* **Extended** 기능은 이식 가능하지만 구현에서 보편적으로 지원되지는 + 않는 기능이다. + 해당 기능을 지원하는 구현은 동일한 동작과 의미를 갖게 된다. + 일부 로드맵 기능은 결국 Core로 마이그레이션될 것으로 예상된다. + Extended 기능은 API 타입과 스키마의 일부가 될 것이다. +* **Implementation-specific** 기능은 이식 가능하지 않고 공급업체별 특정된 기능이다. + Implementation-specific 기능은 일반적인 확장 지점을 통하지 않는 한 + API 타입과 스키마를 가지지 않을 것이다. + +Core 및 Extended 세트의 동작과 기능은 행동 기반 호환성 테스트를 통해 +정의되고 검증될 것이다. Implementation-specific 기능은 호환성 테스트에서 +다루지 않는다. + +API 사양에서 Extended 기능을 포함하고 표준화함으로써, +전체 API 지원을 손상시키지 않으면서 구현 간에 이식 가능한 +API 하위 집합에 수렴할 수 있을 것으로 기대한다. +보편적 지원의 부족은 이식 가능한 기능 세트 개발에 걸림돌이 되지 않을 것이다. +사양에 대한 표준화는 지원이 광범위해질 때 결국 Core로 졸업하는 것을 더 쉽게 만들 것이다. + +### 중첩된 지원 수준 + +특정 필드에 대해 지원 수준이 중첩될 수 있다. +이런 경우가 발생하면 표현된 최소 지원 수준으로 해석되어야 한다. +예를 들어, 동일한 구조체가 두 개의 다른 곳에 포함될 수 있다. +그 중 한 곳에서는 구조체가 Core 지원을 갖는 것으로 간주되고 +다른 곳에서는 Extended 지원만 포함한다. +이 구조체 내의 필드는 별도의 Core 및 Extended 지원 수준을 나타낼 수 있지만, +이러한 수준은 포함된 상위 구조체의 지원 수준을 초과하는 것으로 해석되어서는 안 된다. + +더 구체적인 예로, HTTPRoute는 Rule 내에서 정의된 필터에 대해 Core 지원을 포함하고, +BackendRef 내에서 정의된 경우 Extended 지원을 포함한다. +이러한 필터는 각 필드에 대해 별도로 지원 수준을 정의할 수 있다. +중첩된 지원 수준을 해석할 때 최소값으로 해석되어야 한다. +이는 필드가 Core 지원 수준을 가지더라도 Extended 지원을 갖는 곳에 연결된 필터에 있는 경우, +해석된 지원 수준은 Extended여야 함을 의미한다. + +## 3. 호환성 테스트 + +게이트웨이 API는 호환성 테스트 세트를 포함한다. +이는 지정된 GatewayClass를 사용하여 +일련의 Gateway와 Route를 생성하고, 구현이 API 사양과 일치하는지 테스트한다. + +각 릴리스에는 호환성 테스트 세트가 포함되어 있으며, +API가 발전함에 따라 계속 확장될 것이다. +현재 호환성 테스트는 standard 채널의 +Core 기능 대부분을 다루며, 일부 Extended 기능을 포함한다. + +### 테스트 실행 + +호환성 테스트에는 두 가지 주요 대조적인 세트가 있다. + +* 게이트웨이 관련 테스트 (인그레스 테스트로도 생각할 수 있음) +* 서비스 메시 관련 테스트 + +`Gateway` 테스트의 경우 `Gateway` 테스트 기능을 활성화한 후 +실행하려는 특정 테스트(예: `HTTPRoute`)를 선택해야 한다. +메시 관련 테스트의 경우 `Mesh`를 활성화해야 한다. + +각 사용 사례를 개별로 다루겠지만, +구현이 둘 다 지원하는 경우 이를 결합하는 것도 가능하다. +또한 실행 중인 테스트에 관계없이 전체 테스트 스위트에 적용되는 옵션도 있다. + +#### 게이트웨이 테스트 + +기본적으로 `Gateway` 중심의 호환성 테스트는 클러스터에 `gateway-conformance`라는 +이름의 GatewayClass가 설치되어 있을 것으로 예상하며, 이에 대해 테스트가 +실행된다. 대부분의 경우 다른 클래스를 사용할 것이며, 이는 해당 테스트 명령과 +함께 `-gateway-class` 플래그로 지정할 수 있다. +사용할 `gateway-class` 이름은 당신의 인스턴스에서 확인하자. +또한 `Gateway` 지원과 구현이 지원하는 모든 `*Routes`에 +대한 테스트 지원을 활성화해야 한다. + +다음은 `Gateway`, `HTTPRoute`, `ReferenceGrant`와 관련된 모든 +테스트를 실행한다. + +```shell +go test ./conformance -run TestConformance -args \ + --gateway-class=my-gateway-class \ + --supported-features=Gateway,HTTPRoute +``` + +다른 유용한 플래그는 [호환성 플래그][cflags]에서 찾을 수 있다. + +[cflags]:https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/utils/flags/flags.go + +#### 메시 테스트 + +Mesh 테스트는 단순히 `Mesh` 기능을 활성화하여 실행할 수 있다. + +```shell +go test ./conformance -run TestConformance -args --supported-features=Mesh +``` + +메시가 `HTTPRoute`와 같은 API를 통해 인그레스 지원을 포함하고 있다면, +`Gateway` 기능과 관련 API 기능을 활성화하여 동일한 테스트 실행에서 +관련 테스트를 실행할 수 있다. + +```shell +go test ./conformance -run TestConformance -args --supported-features=Mesh,Gateway,HTTPRoute +``` + +#### 네임스페이스 레이블과 어노테이션 + +테스트에 사용되는 네임스페이스에 레이블이 필요한 경우, `-namespace-labels` 플래그를 +사용하여 테스트 네임스페이스에 설정할 하나 이상의 `name=value` 레이블을 전달할 수 있다. +마찬가지로 `-namespace-annotations` 플래그를 사용하여 테스트 네임스페이스에 적용할 +어노테이션을 지정할 수 있다. +메시 테스트의 경우, 이 플래그는 구현이 메시 워크로드를 호스팅하는 네임스페이스에 레이블을 +요구하는 경우 사용할 수 있다. 예를 들어, 사이드카 주입을 화성화하기 위해 사용할 수 있다. + +예를 들어, Linkerd를 테스트할 때 다음과 같이 실행할 수 있다. + +```shell +go test ./conformance -run TestConformance -args \ + ... + --namespace-annotations=linkerd.io/inject=enabled +``` + +이렇게 하면 테스트 네임스페이스가 메시에 올바르게 주입된다. + +#### 테스트 제외 + +`Gateway` 및 `ReferenceGrant` 기능은 기본적으로 활성화된다. +`-supported-features` 플래그를 사용하여 명시적으로 나열할 필요는 없다. +그러나 실행하지 않으려면 +`-exempt-features` 플래그를 사용하여 비활성화해야 한다. +예를 들어, `Mesh` 테스트만 실행하고 다른 것은 실행하지 않으려면 다음과 같다. + +```shell +go test ./conformance -run TestConformance -args \ + --supported-features=Mesh \ + --exempt-features=Gateway,ReferenceGrant +``` + +#### 스위트 수준 옵션 + +어떤 종류의 테스트를 실행할 때 테스트 스위트가 완료 후 +테스트 리소스를 정리하지 않도록 설정할 수 있다. +(즉, 실패 시 클러스터 상태를 검사할 수 있도록). +`--cleanup-base-resources=false` 플래그를 설정하여 정리를 건너뛸 수 있다. + +(특히 특정 기능을 구현하는 작업을 할 때) 특정 테스트를 이름으로 +실행하는 것이 도움이 될 수 있다. +이는 `--run-test` 플래그를 설정하여 수행할 수 있다. + +#### 네트워크 정책 + +[Container Network Interface (CNI) 플러그인][network_plugins]을 사용하여 +네트워크 정책을 시행하는 클러스터에서는 +일부 호환성 테스트가 트래픽이 필요한 목적지에 도달할 수 있도록 +사용자 정의 [`NetworkPolicy`][netpol] 리소스를 클러스터에 추가해야 할 수 있다. + +사용자는 구현이 해당 테스트를 통과할 수 있도록 +필요한 네트워크 정책을 추가해야 한다. + +[network_plugins]: https://kubernetes.io/ko/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/ +[netpol]: https://kubernetes.io/ko/docs/concepts/services-networking/network-policies/ + +### 호환성 프로필 + +호환성 프로필은 여러 지원 기능을 그룹화하여, 호환성 보고서를 통해 +지원을 인증하는 것을 목표로 하는 도구이다. +지원되는 프로필은 +`--conformance-profiles=PROFILE1,PROFILE2` 플래그를 사용하여 구성할 수 있다. + +## 호환성 보고서 + +스위트가 호환성 프로필 세트를 실행하도록 구성되고 모든 호환성 보고서 필드가 +[이 가이드][conformance-guide]에 따라 적절히 설정된 경우, 호환성 보고서는 +PR을 통해 [이 폴더][reports-folder]에 업로드할 수 있다. 특정 구현에 대한 +보고서를 구성하고 제출하는 방법에 대한 모든 세부 사항은 [가이드][conformance-guide]를 +따르자. + +[reports-folder]: https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports/ +[conformance-guide]: https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports/README.md + +## 호환성에 기여하기 + +많은 구현체는 전체 e2e 테스트 스위트의 일부로 호환성 테스트를 실행한다. +호환성 테스트에 기여한다는 것은 구현이 테스트 개발에 대한 투자를 공유하고 +일관된 경험을 제공하고 있음을 보장할 수 있다는 것을 +의미한다. + +호환성과 관련된 모든 코드는 프로젝트의 "/conformance" 디렉터리에 있다. +테스트 정의는 "/conformance/tests"에 있으며 각 테스트는 두 개의 파일로 구성된다. +YAML 파일에는 테스트 실행 시 적용할 매니페스트가 포함되어 있다. +Go 파일에는 구현체가 해당 매니페스트를 적절히 처리하는지 확인하는 코드가 +포함되어 있다. + +호환성과 관련된 이슈는 +["area/conformance"로 레이블이 지정](https://github.com/kubernetes-sigs/gateway-api/issues?q=is%3Aissue+is%3Aopen+label%3Aarea%2Fconformance) +되어 있다. 이는 종종 테스트 커버리지를 개선하기 위한 새로운 테스트 추가나 기존 테스트의 +결함이나 제한 사항 수정을 다룬다. diff --git a/site-src/ko/concepts/glossary.md b/site-src/ko/concepts/glossary.md new file mode 100644 index 0000000000..5924f274f4 --- /dev/null +++ b/site-src/ko/concepts/glossary.md @@ -0,0 +1,71 @@ +# 게이트웨이 API 용어집 (Gateway API Glossary) + +### 컨슈머 라우트 (Consumer Route) + +워크로드의 서비스에 연결된 라우트로, 특정 소비자(Consumer)에 의해 바인딩되며, +해당 소비자의 워크로드 사용을 세밀하게 조정한다. + + +### 게이트웨이 컨트롤러 (Gateway Controller) + +_게이트웨이 컨트롤러_ 는 게이트웨이 API를 사용하여 컨텍스트들 간 +트래픽 라우팅과 관련된 인프라를 관리하는 소프트웨어로, +이전의 _인그레스 컨트롤러_ 개념과 유사하다. +항상 그런 것은 아니지만, 게이트웨이 컨트롤러는 보통 인프라를 관리하는 클러스터 내에서 실행된다. + + +### 동/서 트래픽 (East/West traffic) + +클러스터 내부 워크로드 간 트래픽 + +### 엔드포인트 라우팅 (Endpoint routing) + +_엔드포인트 라우팅_ 은 특정 서비스에 대한 요청을 +서비스 백엔드의 엔드포인트 중 하나로 직접 전송하여, +기반 네트워크 인프라에 의해 이루어질 수 있는 라우팅 결정을 우회한다. +이는 일반적으로 스티키 세션과 같은 고급 라우팅 사례에서 필요한데, +이 경우 게이트웨이는 특정 세션에 대한 모든 요청이 동일한 엔드포인트로 전달되도록 +보장해야 한다. + +### 북/남 트래픽 (North/South traffic) + +클러스터 외부에서 클러스터 내부로의 트래픽 (반대 방향 포함) + +### 프로듀서 라우트 (Producer Route) + +워크로드의 생산자(Producer)에 의해 워크로드의 서비스에 바인딩된 라우트로, +워크로드의 허용 가능한 사용을 정의한다. +프로듀서 라우트는 항상 해당 워크로드의 서비스와 동일한 네임스페이스에 있어야 한다. + +### 서비스 백엔드 (Service backend) + +쿠버네티스 서비스 리소스의 일부로, 파드와 그 IP와 연관된 엔드포인트 집합. +일부 동/서 트래픽은 워크로드가 서비스 백엔드 내의 특정 엔드포인트로 요청을 +직접 전달함으로써 발생한다. + +### 서비스 프론트엔드 (Service frontend) + +쿠버네티스 서비스 리소스의 일부로, DNS 레코드와 클러스터 IP를 할당한다. +동/서 트래픽은 보통 (항상은 아님) 워크로드가 서비스 프론트엔드로 요청을 +직접 전달함으로써 동작한다. + +### 서비스 메시 (Service mesh) + +_서비스 메시_ 는 워크로드 간 통신 (통/서 트래픽)에 대한 보안, 신뢰성 및 관찰 가능성을 +제공하는 인프라를 관리하는 소프트웨어이다. +서비스 메시는 일반적으로 매우 낮은 수준에서 +워크로드 간 통신을 가로채는 방식으로 동작하며, +보통 (항상은 아님) 워크로드의 파드 옆에 프록시를 삽입하는 방식을 사용한다. + +### 서비스 라우팅 (Service routing) + +_서비스 라우팅_ 은 특정 서비스에 대한 요청을 서비스 프론트엔드로 전송하여, +기반 네트워크 인프라 (일반적으로 `kube-proxy` +또는 [서비스 메시](#service-mesh))가 요청이 라우팅될 +특정 엔드포인트를 선택하도록 한다. + +### 워크로드 (Workload) + +클러스터 내에서 기능을 제공하는 컴퓨팅 인스턴스로, +컴퓨팅을 제공하는 파드와 해당 파드를 소유하는 +디플로이먼트/잡/레플리카셋 등으로 구성된다. \ No newline at end of file diff --git a/site-src/ko/concepts/roles-and-personas.md b/site-src/ko/concepts/roles-and-personas.md new file mode 100644 index 0000000000..1931da38c6 --- /dev/null +++ b/site-src/ko/concepts/roles-and-personas.md @@ -0,0 +1,80 @@ +# 역할과 페르소나 + +## 배경 + +쿠버네티스의 원래 설계에서는, +인그레스와 서비스 리소스가 서비스와 인그레스를 생성하는 개발자들이 +애플리케이션을 정의하고 외부에 노출하는 모든 측면을 제어하는 +사용 모델을 기반으로 한다. + +하지만 실제로는 클러스터와 인프라가 공유되는 경향이 있으며, +원래 인그레스 모델은 이를 잘 반영하지 못한다. +중요한 점은 인프라가 공유될 때 모든 사용자가 +동일한 관심사를 가지지 않으며, +성공적인 인프라 프로젝트는 모든 사용자의 요구를 충족해야 한다. + +이는 근본적인 도전을 제기한다. +인프라 사용자에게 필요한 유연성을 제공하는 동시에 +인프라 소유자의 제어을 유지하려면 어떻게 해야하는가? + +게이트웨이 API는 서로 다른 사용자의 +다양한 요구를 드러내고 논의하기 위한 도구로서, +각각의 역할에 대응하는 _페르소나_ 를 정의하여 +사용성, 유연성, 제어를 균형 있게 유지한다. +게이트웨이 API 내의 설계 작업은 이러한 페르소나를 기준으로 의도적으로 구성된다. + +환경에 따라 한 사람이 여러 역할을 맡을 수 있다는것을 유의하자. +이는 아래에서 논의한다. + +## 주요 역할과 페르소나 + +게이트웨이 API는 세 가지 역할과 페르소나를 정의한다: + +* **Ian** (그/그의)는 _인프라 제공자_ 로, + 여러 격리된 클러스터가 여러 테넌트를 제공하도록 하는 + 인프라 세트를 관리하고 유지하는 책임을 진다. 그는 + 특정 단일 테넌트에 얽매이지 않고, 오히려 모든 테넌트들을 전체적으로 고려한다. + Ian은 종종 클라우드 제공자(AWS, Azure, GCP 등)나 PaaS 제공업체에서 + 일하게 된다. + +* **Chihiro** (그들/그들의)은 _클러스터 운영자_ 로서, + 여러 사용자의 요구를 충족하도록 클러스터를 관리하는 + 책임을 진다. Chihiro는 일반적으로 정책, + 네트워크 접근, 애플리케이션 권한 등에 관심을 가진다. + 마찬가지로, 그들은 특정 클러스터 사용자에게 얽매이지 않고, 클러스터가 + 모든 사용자에게 필요에 따라 서비스를 제공하도록 보장해야 한다. + +* **Ana** (그녀/그녀의)는 _애플리케이션 개발자_ 로서, + 클러스터에서 실행되는 애플리케이션을 생성하고 관리하는 + 책임을 진다. 게이트웨이 API 관점에서 Ana는 구성(예: 타임아웃, + 요청 매칭/필터)과 서비스 구성(예: 백엔드로의 경로 라우팅)을 관리해야 한다. + 그녀는 게이트웨이 API 페르소나 중 독특한 위치에 있으며, + 그녀의 초점은 쿠버네티스나 게이트웨이 API가 아닌, + 애플리케이션이 제공해야 하는 비즈니스 요구에 있다. + 사실, Ana는 게이트웨이 API와 쿠버네티스를 일을 방해하는 + 마찰로 볼 가능성이 높다. + +환경에 따라 여러 역할이 동일한 사용자에게 매핑될 수 있다. + +- 한 명의 사용자에게 위의 모든 역할을 맡기는 것은 셀프 서비스 모델을 재현하는 것이며, + 이는 쿠버네티스 베어메탈에서 운영하는 작은 스타트업에서 실제로 발생할 수 있다. + +- 보다 일반적인 소규모 스타트업의 경우, 클라우드 제공업체의 클러스터를 사용할 것이다. + 이 경우 Ana아ㅘ Chihiro는 같은 사람이 수 있으며, + Ian은 크라우드 제공자 내의 직원(또는 자동화 프로세스!)일 수 있다. + +- 훨씬 더 큰 조직에서는 위의 각 페르소나가 + 서로 다른 사람(아마도 다른 그룹에서 일하며, + 직접적인 접촉이 거의 없을 가능성이 높다)으로 구현될 것으로 예상한다. + +## RBAC + +RBAC(역할 기반 접근 제어)은 쿠버네티스에서 권한 부여를 위해 사용되는 표준 방식이다. +이를 통해 사용자는 특정 범위에서 누가 어떤 리소스에 대해 작업을 수행할 수 있는지를 +설정할 수 있다. +우리는 각 페르소나가 쿠버네티스 역할 기반 인증(RBAC) 시스템의 `Role`에 대략적으로 매핑되며, +이를 통해 리소스 모델의 책임과 분리를 정의하게 될 것으로 예상한다. + +RBAC는 [보안 모델] 설명에서 더 자세히 논의한다. + +[보안 모델]: security-model.md#rbac diff --git a/site-src/ko/concepts/security-model.md b/site-src/ko/concepts/security-model.md new file mode 100644 index 0000000000..7ce163c105 --- /dev/null +++ b/site-src/ko/concepts/security-model.md @@ -0,0 +1,111 @@ +# 보안 모델 + +## 소개 +게이트웨이 API는 일반적인 조직 내 각 역할에 대해 세분화된 권한 부여를 가능하게 하도록 +설계되었다. + +## 리소스 +게이트웨이 API는 3개의 주요 API 리소스를 가진다. + +* **GatewayClass**는 + 공통 구성과 동작을 가진 게이트웨이 세트를 정의한다. +* **Gateway**는 + 트래픽이 클러스터 내의 서비스로 변환될 수 있는 지점을 요청한다. +* **Routes**는 + 게이트웨이를 통해 들어오는 트래픽이 서비스에 매핑되는 방식을 설명한다. + +## 역할과 페르소나 + +게이트웨이 API에는 역할과 페르소나에 설명된 3개의 주요 역할이 있다. + +- **Ian** (그/그의): 인프라 제공자 +- **Chihiro** (그들/그들의): 클러스터 운영자 +- **Ana** (그녀/그녀의): 애플리케이션 개발자 + +[역할과 페르소나]:roles-and-personas.md + +### RBAC + +RBAC (역할 기반 접근 제어)는 쿠버네티스 권한 부여를 위해 사용되는 표준 방식이다. +이를 통해 사용자는 특정 범위 내에서 누가 어떤 리소스에 대해 작업을 수행할 수 있는지를 설정할 수 있다. +RBAC는 앞서 정의한 각 역할에 대해 권한을 부여하는 데 사용할 수 있다. 대부분의 경우, 모든 리소스를 +대부분의 역할이 읽을 수 있도록 허용하는 것이 바람직하므로, 이 모델에서는 쓰기 권한에 초점을 맞춰 설명한다. + +#### 간단한 3계층 모델에 대한 쓰기 권한 +| | 게이트웨이 클래스 | 게이트웨이 | 라우트 | +|-|-|-|-| +| 인프라 제공자 | 있음 | 있음 | 있음 | +| 클러스터 운영자 | 없음 | 있음 | 있음 | +| 애플리케이션 개발자 | 없음 | 없음 | 있음 | + +#### 고급 4계층 모델에 대한 쓰기 권한 +| | 게이트웨이 클래스 | 게이트웨이 | 라우트 | +|-|-|-|-| +| 인프라 제공자 | 있음 | 있음 | 있음 | +| 클러스터 운영자 | 때에따라 있음 | 있음 | 있음 | +| 애플리케이션 관리자 | 없음 | 지정된 네임스페이스에 한함 | 지정된 네임스페이스에 한함 | +| 애플리케이션 개발자 | 없음 | 없음 | 지정된 네임스페이스에 한함 | + +## 네임스페이스 경계 넘기 +게이트웨이 API는 네임스페이스 경계를 넘는 새로운 방식을 제공한다. +이러한 교차 네임스페이스 기능은 매우 강력하지만, +실수로 리소스가 노출되지 않도록 주의해서 사용해야 한다. +기본 원칙은 네임스페이스 경계를 넘는 경우마다 반드시 양측 간의 핸드셰이크가 있어야 한다는 것이다. +이러한 핸드셰이크는 두 가지 방식으로 이루어질 수 있다. + +### 1. 라우트 바인딩 +라우트는 다른 네임스페이스에 있는 게이트웨이에 연결될 수 있다. +이를 위해서는 게이트웨이 소유자가 명시적으로 다른 네임스페이스의 라우트가 바인딩되도록 허용해야 한다. +이는 게이트웨이의 리스너 내에서 allowedRoutes를 설정함으로써 이루어지며, +설정 예시는 다음과 같다. + +```yaml +namespaces: + from: Selector + selector: + matchExpressions: + - key: kubernetes.io/metadata.name + operator: In + values: + - foo + - bar +``` + +이렇게 하면 "foo"와 "bar" 네임스페이스의 라우트가 +이 게이트웨이 리스너에 연결될 수 있다. + +#### 다른 레이블의 위험 +이 선택자에서 다른 레이블을 사용하는 것도 가능하지만, 그렇게 하면 안전성이 떨어진다. +kubernetes.io/metadata.name 레이블은 네임스페이스에 대해 항상 해당 네임스페이스의 이름으로 +설정되므로 신뢰할 수 있지만, 다른 레이블들은 이런 보장이 없다. +예를 들어 env와 같은 사용자 정의 레이블을 사용할 경우, +클러스터 내에서 네임스페이스에 레이블을 설정할 수 있는 사람은 누구나 게이트웨이가 +지원하는 네임스페이스의 범위를 효과적으로 변경할 수 있게 된다. + +### 2. 레퍼런스그랜트 (ReferenceGrant) +경계를 넘는 또 다른 경우로는 게이트웨이가 시크릿을 참조하거나, +라우트가 백엔드(보통 서비스)를 참조하는 상황이 있다. +이런 경우에는 레퍼런스그랜트 리소스를 사용하여 필요한 핸드셰이크를 수행한다. +레퍼런스그랜트는 대상 네임스페이스에 존재하며, +다른 네임스페이스로부터의 참조를 허용하기 위해 사용된다. + +예를 들어, 아래 레퍼런스그랜트는 "prod" 네임스페이스에 있는 +HTTPRoute가 레퍼런스그랜트와 같은 네임스페이스에 +배포된 서비스를 참조할 수 있도록 허용한다. + +```yaml +{% include 'standard/reference-grant.yaml' %} +``` + +레퍼런스그랜트에 대한 더 자세한 정보는 +[이 리소스에 대한 상세 문서](../api-types/referencegrant.md)를 참고하자. + +## 고급 개념: 게이트웨이 클래스를 사용할 수 있는 네임스페이스 제한하기 +일부 인프라 제공자 또는 클러스터 운영자는 게이트웨이 클래스를 사용할 수 있는 네임스페이스를 +제한하고 싶을 수 있다. 현재 API에는 이에 대한 솔루션이 내장되어 있지 않다. +대신, Open Policy Agent 및 +[Gatekeeper](https://github.com/open-policy-agent/gatekeeper)와 같은 정책 +에이전트를 사용하여 이러한 정책을 시행할 것을 권장한다. +참고로, 이에 사용할 수 있는 +[구성 예제](https://github.com/open-policy-agent/gatekeeper-library/pull/24)가 +있다. diff --git a/site-src/ko/concepts/tooling.md b/site-src/ko/concepts/tooling.md new file mode 100644 index 0000000000..9e3a57ee1c --- /dev/null +++ b/site-src/ko/concepts/tooling.md @@ -0,0 +1,23 @@ +# 도구 + +게이트웨이 API는 리소스와의 상호작용을 쉽게 하기 위한 다양한 도구를 제공한다. + +## `ingress2gateway` + +기존 인그레스 리소스가 게이트웨이 API에서 어떻게 보일지 궁금한가? `ingress2gateway`는 프로바이더별 인그레스 리소스를 게이트웨이 API 리소스로 변환할 수 있는 간편한 도구다. 이 도구는 게이트웨이 API SIG-Network 하위 프로젝트에서 관리한다. + +[kubernetes-sigs/ingress2gateway: 설치 가이드](https://github.com/kubernetes-sigs/ingress2gateway?tab=readme-ov-file#installation)로 시작하기! + +## `gwctl` + +게이트웨이 API 리소스를 관리하기 위한 커맨드라인 도구다. 정책, xRoute 등을 탐색하고 리소스와 상호작용할 수 있다. + +[kubernetes-sigs/gwctl: 설치 가이드](https://github.com/kubernetes-sigs/gwctl?tab=readme-ov-file#installation)로 시작하기! + +## Third-Party Tooling + +### `policy-machinery` + +게이트웨이 API 정책 및 정책 컨트롤러 구현을 위한 프레임워크 + +[Kuadrant/policy-machinery](https://github.com/Kuadrant/policy-machinery/tree/main)에서 시작하기 diff --git a/site-src/ko/concepts/use-cases.md b/site-src/ko/concepts/use-cases.md new file mode 100644 index 0000000000..1a797cbd53 --- /dev/null +++ b/site-src/ko/concepts/use-cases.md @@ -0,0 +1,193 @@ +# 사용 사례 + +게이트웨이 API는 _매우_ 다양한 사용 사례를 다룬다(이는 강점이자 약점이다!). +이 페이지는 이러한 사용 사례의 전체 목록을 제공하려는 것이 _아니다_. +대신, API가 어떻게 사용될 수 있는지를 보여주는 데 +도움이 될 수 있는 몇 가지 예시를 제공하는 것이 목적이다. + +모든 경우에, 게이트웨이 API에서 사용되는 [역할과 페르소나]를 염두에 두는 것이 매우 중요하다. +여기서 제시하는 사용 사례는 의도적으로 +[Ana], [Chihiro], [Ian]이라는 인물들을 중심으로 설명된다. +이들이 바로 API가 사용 가능해야 하는 대상이다. +(특히 소규모 조직에서는 이 역할들이 같은 사람에 의해 수행될 수도 있지만, +각 역할은 분명히 구분되는 서로 다른 관심사를 가지고 있다는 점을 +별도로 고려하는 것이 중요하다.) + +[역할과 페르소나]:roles-and-personas.md +[Ana]:roles-and-personas.md#key-roles-and-personas +[Chihiro]:roles-and-personas.md#key-roles-and-personas +[Ian]:roles-and-personas.md#key-roles-and-personas + +## 사용 사례 목록 + +- [사용 사례](#_1) + - [사용 사례 목록](#_2) + - [기본 북/남(North/South) 사용 사례](#_3) + - [단일 게이트웨이 뒤에 여러 애플리케이션](#_4) + - [기본 동/서(East/West) 사용 사례](#_5) + - [게이트웨이와 메시 결합 사용 사례](#_6) + +[역할과 페르소나]:roles-and-personas.md + +## 기본 [북/남] 사용 사례 + +??? success "v0.8.0 부터 표준 채널" + + [북/남] 사용 사례는 `v0.8.0`부터 표준 채널에서 완전히 지원된다. + 릴리스 채널에 대한 자세한 내용은 + [버전 관리 가이드](versioning.md)를 참고하자. + +Ana는 쿠버네티스에서 실행하고 싶은 마이크로서비스 애플리케이션을 만들었다. +이 애플리케이션은 클러스터 외부의 클라이언트가 사용할 것이며, +Ana는 애플리케이션을 만들었지만 클러스터를 직접 세팅하는 것은 그녀의 전문이 +아니다. + +1. Ana는 Chihiro에게 클러스터를 세팅해달라고 요청한다. + Ana는 Chihiro에게 자신의 클라이언트들이 `https://ana.application.com/`을 + 기반으로 하는 URL을 통해 API를 사용할 것으로 기대한다고 말한다. + +2. Chihiro는 Ian에게 클러스터를 요청한다. + +3. Ian은 `basic-gateway-class`라는 [게이트웨이 클래스] 리소스를 가진 + 게이트웨이 컨트롤러가 실행되는 클러스터를 프로비저닝한다. + 게이트웨이 컨트롤러는 클러스터 외부에서 내부로 트래픽을 라우팅하는 인프라와 + 관련된 작업을 관리한다. + +4. Ian은 Chihiro에게 새 클러스터의 자격 증명을 제공하고, + `basic-gateway-class` 게이트웨이 클래스를 사용해 설정할 수 있다고 알려준다. + +5. Chihiro는 클러스터에 `ana-gateway`라는 [게이트웨이]를 적용하고, 443 포트에서 TLS 트래픽을 수신하도록 설정하며, + Subject CN이 `ana.application.com`인 TLS 인증서를 제공한다. + 이 게이트웨이는 `basic-gateway-class` 게이트웨이 클래스와 연결된다. + +6. 3단계에서 Ian이 프로비저닝한 게이트웨이 컨트롤러는 + `ana-gateway`에 대한 로드 밸런서와 IP 주소를 할당하고, + 443 포트로 들어오는 요청을 라우팅할 수 있는 + 데이터 플레인 컴포넌트를 프로비저닝하며, + `ana-gateway`와 연관된 라우팅 리소스를 감시하기 시작한다. + +7. Chihiro는 `ana-gateway`의 IP 주소를 받아 클러스터 외부에서 + `ana.application.com`에 대한 DNS 레코드를 생성하여 일치시킨다. + +8. Chihiro는 Ana에게 `ana-gateway`라는 게이트웨이를 사용할 수 있다고 + 알린다. + +9. Ana는 어떤 URL 경로가 허용되고 어떤 마이크로서비스가 이를 처리할지 설정하는 + [HTTPRoute] 리소스를 작성하고 적용한다. + 그녀는 [라우트 연결 프로세스]를 사용하여 이러한 HTTPRoutes를 + `ana-gateway`와 연관시킨다. + +10. 이 시점에서, 로드 밸런서에 도착하는 요청은 Ana의 라우팅 명세에 따라 + Ana의 애플리케이션으로 트래픽이 라우팅된다. + +이것은 Chihiro가 게이트웨이에서 [TLS](../guides/tls.md#downstream-tls)와 +같은 중앙 정책을 강제할 수 있게 하며, +동시에 Ana와 동료들은 애플리케이션의 [라우팅 로직](../guides/http-routing.md)과 +롤아웃 계획(예: [트래픽 분할 롤아웃](../guides/traffic-splitting.md))을 +직접 제어할 수 있도록 허용한다. + +[북/남]:glossary.md#northsouth-traffic + +## 단일 게이트웨이 뒤에 여러 애플리케이션 + +??? success "v0.8.0 부터 표준 채널" + + [북/남] 사용 사례는 `v0.8.0`부터 표준 채널에서 완전히 지원된다. + 릴리스 채널에 대한 자세한 내용은 + [버전 관리 가이드](versioning.md)를 참고하자. + +이 사례는 +[기본 북/남 사용 사례](#_3)와 놀라울 정도로 유사하지만, +여러 애플리케이션 팀이 존재한다. +Ana와 그녀의 팀은 `store` 네임스페이스에서 스토어프론트 애플리케이션을 관리하고, +Allison과 그녀의 팀은 `site` 네임스페이스에서 웹사이트를 관리한다. + +- Ian과 Chihiro는 위와 같이 클러스터, + `GatewayClass`, `Gateway`를 함께 제공한다. + +- Ana와 Allison은 각각 워크로드와 HTTPRoute를 + 동일한 `Gateway` 리소스에 독립적으로 배포한다. + +이렇게 역할을 분리하면 +Chihiro가 게이트웨이에서 [TLS](../guides/tls.md#downstream-tls)와 같은 중앙 정책을 강제할 수 있다. +한편, Ana와 Allison은 [각자의 네임스페이스](../guides/multiple-ns.md)에서 애플리케이션을 운영하면서 +동일한 공유 게이트웨이에 라우트를 연결해, +[라우팅 로직](../guides/http-routing.md), +[트래픽 분할 롤아웃](../guides/traffic-splitting.md) 등을 +독립적으로 제어할 수 있고, +Chihiro와 Ian이 처리하는 부분은 신경 쓰지 않아도 된다. + +[HTTPRoute]:../api-types/httproute.md +[게이트웨이 클래스]:../api-types/gatewayclass.md +[게이트웨이]:../api-types/gateway.md +[라우트 연결 프로세스]:api-overview.md#attaching-routes-to-gateways + +![게이트웨이 API 역할](../images/gateway-roles.png) + +## 기본 [동/서] 사용 사례 + +이 시나리오에서 +Ana는 이미 [GAMMA] 호환 [서비스 메시]가 실행 중인 클러스터에 워크로드를 배포했다. +Ana는 메시를 활용해 잘못된 URL 경로로 들어오는 요청을 거부하고, +모든 요청에 타임아웃을 적용함으로써 워크로드를 보호하고자 +한다. + +- Chihiro와 Ian은 이미 서비스 메시가 실행 중인 클러스터를 제공했다. + Ana는 이들에게 별도의 요청을 할 필요가 없다. + +- Ana는 허용 가능한 라우트와 타임아웃을 정의하고, + 자신의 워크로드 서비스에 `parentRef`를 지정한 HTTPRoute를 작성한다. + +- Ana는 자신의 워크로드와 동일한 네임스페이스에 HTTPRoute를 적용한다. + +- 메시는 Ana가 정의한 HTTPRoute에 따라 라우팅 정책을 자동으로 적용하기 + 시작한다. + +이 경우 역할 간의 관심사 분리는 +Ana가 커스텀 라우팅 로직과 함께 서비스 메시를 활용할 수 있게 해주며, +Chihiro나 Ian에게의 요청에서 병목 없이 이를 수행할 수 있게 한다. + +[동/서]:glossary.md#eastwest-traffic +[GAMMA]:../mesh/index.md +[서비스 메시]:glossary.md#service-mesh + +## 게이트웨이와 메시 결합 사용 사례 + +이는 사실상 +[단일 게이트웨이 뒤에 여러 애플리케이션이 있는 경우](#_4)와 [기본 동/서 사용 사례](#_5)를 +결합한 형태다. + +- Chihiro와 Ian은 클러스터, [게이트웨이 클래스], [게이트웨이]를 프로비저닝할 것이다. + +- Ana와 Allison은 각자의 네임스페이스에 그들의 애플리케이션을 + 배포할 것이다. + +- Ana와 Allison은 이후 적절하게 HTTPRoute 리소스를 적용할 것이다. + +이 시나리오에서는 메시가 포함되어 있기 때문에 두 가지 매우 중요한 +변화가 있다. + +1. Chihiro가 [서비스 라우팅]을 사용하는 [게이트웨이 컨트롤러]를 배포했다면, + [엔드포인트 라우팅]으로 재구성해야 할 가능성이 크다. + (이는 [GAMMA]에서 진행 중인 작업 영역이며, + 엔드포인트 라우팅이 권장될 전망이다.) + +2. Ana와/또는 Allison은 메시 라우팅 로직을 구성하기 위해 + HTTPRoute를 각자의 워크로드 서비스에 바인딩해야 한다. + 이 HTTPRoute들은 메시 전용의 별도일 수도 있고, + 게이트웨이와 서비스 모두에 바인딩되는 단일 HTTPRoute일 수도 있다. + +언제나 그렇듯, 이런 방식으로 관심사를 분리하는 궁극적인 목적은 +Chihiro가 게이트웨이에서 [TLS](../guides/tls.md#downstream-tls)와 같은 +중앙 정책을 강제할 수 있게 하면서, +Ana와 Allison이 +[라우팅 로직](../guides/http-routing.md), [트래픽 분할 롤아웃](../guides/traffic-splitting.md) 등을 +독립적으로 제어할 수 있도록 허용하는 것이다. +이는 [북/남]과 [동/서] 라우팅 모두에 해당한다. + + + + +[게이트웨이 컨트롤러]:glossary.md#gateway-controller +[서비스 라우팅]:glossary.md#service-routing +[엔드포인트 라우팅]:glossary.md#endpoint-routing diff --git a/site-src/ko/concepts/versioning.md b/site-src/ko/concepts/versioning.md new file mode 100644 index 0000000000..280be49330 --- /dev/null +++ b/site-src/ko/concepts/versioning.md @@ -0,0 +1,184 @@ +# 버전 관리 + +## 개요 +게이트웨이 API의 각 새로운 릴리스는 v1.0.0과 같은 릴리스의 Git 태그를 나타내는 +"번들 버전"으로 정의한다. +이 번들은 다음을 포함한다. + +* API 타입(리소스에 대한 Go 바인딩) +* CRD(리소스에 대한 쿠버네티스 정의) + +### 릴리스 채널 +릴리스 채널은 게이트웨이 API 내에서 기능의 안정성을 나타내는 데 사용된다. +모든 새로운 기능과 리소스는 실험적 릴리스 채널에서 시작된다. +그 후, +이들은 표준 릴리스 채널로 승격되거나 API에서 완전히 제거될 수 있다. + +아래 다이어그램은 게이트웨이 API에서 새로운 +[GEP](../geps/overview.md)(기능 향상 제안서)로 제안된 기능이나 +리소스의 라이프사이클에 대한 높은 수준의 개요를 제공한다. + +```mermaid +flowchart TD + 0([Implementable GEP]) --> A + A>Experimental Channel] --> B([Widely used and working well?]) + B -->|Yes| C>Standard Channel] + B -->|No| D([Could Changes Help?]) + D -->|Yes| E([Adjust and try again]) + D -->|No| F>Remove From API] + E -->A + +style A fill:#eeb +style C fill:#beb +style F fill:#ebb +``` + +표준 릴리스 채널에는 다음이 포함된다. + +* beta 또는 GA API 버전으로 승격된 리소스(beta API 버전은 게이트웨이 API에서 점진적으로 제거되고 있다는 점에 + 유의해야 한다.) +* 실험적 채널에서 표준 채널로 승격된 모든 필드 + +실험적 릴리스 채널에는 표준 채널에 포함된 모든 항목에 추가로 다음을 +포함한다. + +* alpha API 버전의 리소스 +* 표준 채널로 승격되기 전의 모든 신규 필드 + +![릴리스 채널 오버랩](../images/release-channel-overlap.svg) + + +기본적으로 안정적인 사용 경험을 제공하므로 표준 채너을 사용하는 것을 권장한다. +많은 구현체드이 실험적 채널도 지원하며, 이를 통해 새로운 기능을 빠르게 반복 개발할 수 있다. +이 채널은 이전 버전과의 호환성에 대한 보장을 제공하지 않으며, +언제든지 호환되지 않는 변경 사항이 +릴리스될 수 있다는 점에 유의해야 한다. + +### API 버전 +업스트림 쿠버네티스 API는 안정성 수준을 alpha, beta, GA API 버전의 세 가지로 구분한다. +게이트웨이 API에서는 위에서 설명한 릴리스 채널을 통해 +이를 두 가지 안정성 수준으로 축소하였다. + +일반적으로, 리소스가 실험적 채널에서 표준 채널로 승격될 때, +Alpha API 버전(v1alpha2)에서 GA API 버전(v1)으로도 +승격된다는 것을 의미한다. + +#### 근거 +아래와 같은 이유로 beta는 점진적으로 제거되고 있다. + +1. 대부분의 경우 API 안정성 수준은 실질적으로 두 가지이다. + - 기본적(stable)으로 설치되는 상태와 alpha/experimental(unstable) 상태 + 게이트웨이 API에서는 중간 단계 (Beta 상태)의 가치가 명확하지 않다. +2. "안정(stable)"과 "실험적(experimental)" API를 더 멀리 분리할수록, + 새로운 기능에 대한 의미 있는 피드백을 얻는 데 더 오래 걸린다. +3. 우리가 관리하는 각 고유 API 버전은 + 사용자, 구현자, 유지관리자 모두에게 상당한 추가 비용을 발생시킨다. + +#### 베타 +일부 게이트웨이 API 리소스는 표준 채널로 승격될 때 Beta API 버전을 받은 경우가 있지만, +앞으로 추가되는 리소스에는 해당되지 않는다. +앞으로 표준 채널로 승격되는 모든 리소스는 +그 과정의 일부로 v1 API 버전을 포함하게 된다. + +이미 beta API 버전(v1beta1)을 가진 리소스는 다음과 같다. + +* HTTPRoute +* 게이트웨이(Gateway) +* 게이트웨이 클래스(GatewayClass) +* 레퍼런스그랜트(ReferenceGrant) + +v1.0 릴리스에서 HTTPRoute, 게이트웨이, 게이트웨이 클래스는 모두 GA API 버전(v1)으로 +승격되었다. + +레퍼런스그랜트는 예외적이다. +이 리소스는 +현재 [상위 쿠버네티스 API로 전환](https://github.com/kubernetes/enhancements/issues/3766) 중이며, +[sig-auth](https://github.com/kubernetes/community/blob/master/sig-auth/README.md)에서 +관리한다. +이 과정이 완료될 때까지 레퍼런스그랜트는 게이트웨이 API에서 사실상 베타로 동결될 가능성이 높다. +레퍼런스그랜트가 내장 쿠버네티스 API로 널리 제공되면, +게이트웨이 API의 표준 채널에서 제거할 예정이다. + +## 버전 표시 +각 CRD는 번들 버전과 채널을 나타내는 어노테이션과 함께 +배포된다. + +``` +gateway.networking.k8s.io/bundle-version: v0.4.0 +gateway.networking.k8s.io/channel: standard|experimental +``` + +## 변경 가능한 것 +이 API를 사용하거나 구현할 때, +번들 버전 간에 무엇이 변경될 수 있는지 이해하는 것이 중요하다. + +### 패치 버전(예: v0.4.0 -> v0.4.1) +* API 명세: + * 명확성 개선 + * 오타 수정 +* 버그 수정: + * 유효성 검사 수정 + * 릴리스 프로세스 또는 산출물 수정 +* 호환성 테스트: + * 기존 테스트 수정 + * 기존 기능에 대한 호환성 테스트 커버리지 추가 + +### 마이너 버전(예: v0.4.0 -> v0.5.0) +* 패치 릴리스에서 유효한 모든 변경 +* 실험적 채널: + * 새로운 API 필드 또는 리소스 추가 + * 기존 API 필드 또는 리소스에 대한 중대 변경 + * 사전 사용 중단(deprecation) 없이 API 필드 또는 리소스 제거 +* 표준 채널: + * 실험적에서 표준 채널로의 필드 또는 리소스 승격 + * [쿠버네티스 사용 중단 정책](https://kubernetes.io/docs/reference/using-api/deprecation-policy/)에 따라 + API 리소스 제거 +* 모든 채널: + * 상태에서 권장 조건 또는 사유 변경 + * 유효성 검사 완화(필수 필드를 선택적 필드로 변경 등) + * 명세 업데이트에 맞춘 호환성 테스트 변경 + * 필드명 변경이나 + [새로운 쿠버네티스 API 버전](https://kubernetes.io/ko/docs/reference/using-api/#api-%EB%B2%84%EC%A0%84-%EA%B7%9C%EC%B9%99)에서 + 유효한 기타 모든 변경 사항을 포함할 수 있는 새로운 API 버전의 도입 + +### 메이저 버전(예: v0.x -> v1.0) +* 메이저 버전이 변경될 때는 API 호환성 보장을 하지 않는다. + +## 승격 기준 +리소스, 필드, 기능이 실험적에서 표준으로 승격되기 위해서는 +다음 기준을 충족해야 한다. + +* 완전한 호환성 테스트 커버리지 +* 여러 구현체에서 호환성 통과 +* 광범위한 구현 및 사용 +* alpha API로 최소 6개월간 운영된 시간(soak time) +* 최소 1회 마이너 릴리스 및 3개월간 주요 변경 없음 +* 서브프로젝트 오너 및 KEP 리뷰어 승인 + +## 지원 버전 +이 프로젝트는 다양한 쿠버네티스 버전에서 일관된 업그레이드 경험을 지원하는 것을 목표로 한다. +이를 달성하기 위해 다음과 같은 사항을 준수한다. + +1. 가장 최근 쿠버네티스 마이너 버전 5개 이상을 최소 지원 대상으로 한다. +2. v1beta1과 v1 사이의 표준 채널 변경은 모두 완전히 + 호환 및 변환 가능하도록 보장한다. +3. 변환(conversion) 웹훅 도입은 최대한 피하도록 노력한다. + 만약 변환 웹훅이 도입되어야 할 경우, + 해당 API의 라이프타임 동안 또는 최소한 대안이 제공될 때까지 지원한다. + +## CRD 관리 +클러스터에서 게이트웨이 API CRD를 관리하는 방법은 [CRD 관리 가이드](../guides/crd-management.md)를 +참고하자. + +## 범위 외 항목 +### 미출시 API +이 프로젝트는 main 브랜치에 자주 업데이트가 발생한다. +main을 포함한 어떤 브랜치의 코드에도 릴리스되기 전까지는 호환성 보장이 없다. +예를 들어, 릴리스가 공개되기 전에 변경이 되돌려질 수 있다. +최상의 결과를 위해서는 이 프로젝트의 최신 공개 릴리스를 +사용하는 것이 좋다. + +### 소스 코드 +소스 코드 import에 대한 안정성은 보장하지 않는다. +인터페이스와 동작은 향후 릴리스에서 예기치 않게, +그리고 이전 버전과 호환되지 않는 방식으로 변경될 수 있다. diff --git a/site-src/ko/contributing/contributor-ladder.md b/site-src/ko/contributing/contributor-ladder.md new file mode 100644 index 0000000000..b7df292c5d --- /dev/null +++ b/site-src/ko/contributing/contributor-ladder.md @@ -0,0 +1,133 @@ +# Contributor Ladder + +Within the Kubernetes community, the concept of a contributor ladder has been +developed to define how individuals can earn formal roles within the project. +The Gateway API contributor ladder largely follows the [roles defined by the +broader Kubernetes +community](https://github.com/kubernetes/community/blob/master/community-membership.md), +though there are some aspects that are unique to this community. + +## Goals + +We hope that this doc will provide an initial step towards the following goals: + +* Ensure the long term health of the Gateway API community +* Encourage new contributors to work towards formal roles and responsibilities + in the project +* Clearly define the path towards leadership roles +* Develop a strong leadership pipeline so we have great candidates to fill + project leadership roles + + +## Scope + +The following repositories are covered by this doc: + +* [kubernetes-sigs/gateway-api](https://github.com/kubernetes-sigs/gateway-api) +* [kubernetes-sigs/ingress2gateway](https://github.com/kubernetes-sigs/ingress2gateway) +* [kubernetes-sigs/gwctl](https://github.com/kubernetes-sigs/gwctl) +* [kubernetes-sigs/blixt](https://github.com/kubernetes-sigs/blixt) + +Within each of these projects, there are opportunities to become an approver or +reviewer for either the entire project, or a subset of that project. For +example, you could become a reviewer or approver focused on just docs, GEPs, API +changes, or conformance tests. + +## General Guidelines + +### 1. Everyone is welcome + +We appreciate all contributions. You don’t need to have a formal role in the project to make or review pull requests, and help with issues or discussions. Accepting a formal role within the project is entirely optional. + +### 2. These roles require continued contributions + +Applying for one of the roles defined above should only be done if you intend to +continue to contribute at a level that would merit that role. If for any reason +you are unable to continue in one of the roles above, please resign. Members +with an extended period away from the project with no activity will be removed +from the Kubernetes GitHub Organizations and will be required to go through the +org membership process again after re-familiarizing themselves with the current +state. + +### 3. Don’t merge without consensus + +If you have reason to believe that a change may be contentious, please wait for +additional perspectives from others before merging any PRs. Even if you have +access to merge a PR, it doesn’t mean you should. Although we can’t have PRs +blocked indefinitely, we need to make sure everyone has had a chance to present +their perspective. + +### 4. Start a discussion + +If you’re interested in working towards one of these roles, please reach out to +a Gateway API maintainer on Slack. + +## Contributor Ladder + +The Gateway API contributor ladder has the following steps: + +1. Member +2. Reviewer +3. Approver +4. Maintainer + +This is also a GAMMA-specific leadership role that does not fit as cleanly on +this ladder. All of these roles will be defined in more detail below. + +## Member, Reviewer, and Approver + +The first steps on the contributor ladder are already [clearly defined in the +upstream Kubernetes +Community](https://github.com/kubernetes/community/blob/master/community-membership.md#community-membership). +Gateway API follows those guidelines along with the rest of the Kubernetes +community. Within Gateway API, there are a variety of areas one can become a +reviewer or approver, this includes: + +* Conformance +* Documentation +* GEPs + +## Maintainers and GAMMA Leads + +The final steps on the contributor ladder represent large overall leadership +roles within the project as a whole. The spaces available for these roles are +limited (generally 3-4 people in each role is ideal). Wherever possible, we try +to ensure that different companies are represented in these roles. + +### Maintainers + +Gateway API Maintainers are known as [Subproject +Owners](https://github.com/kubernetes/community/blob/master/community-membership.md#subproject-owner) +within the Kubernetes community. To become a Gateway API Maintainer, the most +important things we expect are: + +* Long term, sustained contributions to Gateway API for at least 6 months +* Deep understanding of technical goals and direction of the project +* Successfully authored and led significant enhancement proposals +* Approver for at least 3 months +* Ability to lead community meetings + +In addition to all of the expectations described above, we expect maintainers to +set the technical direction and goals for the project. This role is critical to +the health of the project, maintainers should mentor new approvers and +reviewers, and ensure that there are healthy processes in place for discussion +and decision making. Finally, maintainers are ultimately responsible for +releasing new versions of the API. + +## GAMMA Leads + +The concept of GAMMA Leads does not have a perfect parallel on the upstream +Kubernetes community ladder. They are essentially Subproject Owners, but for the +GAMMA initiative, which is a major initiative within Gateway API. + +To become a GAMMA lead, the most important thing we expect are: + +* Significant experience with Service Mesh implementation(s) +* Deep understanding of technical goals and direction of the project +* Long term, sustained contributions to the GAMMA initiative for at least 6 months +* Ability to lead community meetings + +In addition to all of the expectations described above, we expect GAMMA Leads to +set the technical direction and goals for the GAMMA initiative. They should +ensure that there are healthy processes in place for discussion and decision +making and that the release goals and milestones are clearly defined. diff --git a/site-src/ko/contributing/devguide.md b/site-src/ko/contributing/devguide.md new file mode 100644 index 0000000000..c8c23716a7 --- /dev/null +++ b/site-src/ko/contributing/devguide.md @@ -0,0 +1,171 @@ +# Developer Guide +# 개발자 가이드 + +## Project Management +## 프로젝트 관리 + +We are using the GitHub issues and project dashboard to manage the list of TODOs +for this project: +우리는 이 프로젝트의 할 일 목록을 관리하기 위해 GitHub 이슈와 프로젝트 대시보드를 활용하고 있다. + + +* [Open issues][gh-issues] +* [Project dashboard][gh-dashboard] +* [이슈 열기][gh-issues] +* [프로젝트 대시보드][gh-dashboard] + +Issues labeled `good first issue` and `help wanted` are especially good for a +first contribution. +`good first issue`와 `help wanted`라고 표시된 이슈는 특히 +첫 번째 기여에 특히 좋다. + +We use [milestones][gh-milestones] to track our progress towards releases. +These milestones are generally labeled according to the [semver][semver] +release version tag that they represent, meaning that in general we only focus +on the next release in the sequence until it is closed and the release is +finished. Only Gateway API maintainers are able to create and attach issues to +milestones. + +We use [priority labels][prio-labels] to help indicate the timing importance of +resolving an issue, or whether an issue needs more support from its creator or +the community to be prioritized. These labels can be set with the [/priority +command in PR and issue comments][issue-cmds]. For example, +`/priority important-soon`. + +[gh-issues]: https://github.com/kubernetes-sigs/gateway-api/issues +[gh-dashboard]: https://github.com/kubernetes-sigs/gateway-api/projects +[gh-milestones]: https://github.com/kubernetes-sigs/gateway-api/milestones +[semver]:https://semver.org/ +[prio-labels]:https://github.com/kubernetes-sigs/gateway-api/labels?q=priority +[issue-cmds]:https://prow.k8s.io/command-help?repo=kubernetes-sigs%2Fgateway-api + +## Prerequisites + +Before you start developing with Gateway API, we'd recommend having the +following prerequisites installed: + +* [Kind](https://kubernetes.io/docs/tasks/tools/#kind): This is a standalone local Kubernetes cluster. At least one container runtime is required. We recommend installing [Docker](https://docs.docker.com/engine/install/). While you can opt for alternatives like [Podman](https://podman.io/docs/installation), please be aware that doing so is at your own risk. +* [Kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl): This is the Kubernetes command-line tool. +* [Go](https://golang.org/doc/install): It is the main programming language in this project. Please check this [file](https://github.com/kubernetes-sigs/gateway-api/blob/main/go.mod#L3) to find out the least `Go` version otherwise you might encounter compilation errors. +* [Digest::SHA](https://metacpan.org/pod/Digest::SHA): It is a required dependency. You can obtain it by installing the `perl-Digest-SHA` package. + + +## Development: Building, Deploying, Testing, and Verifying + +Clone the repo: + +``` +mkdir -p $GOPATH/src/sigs.k8s.io +cd $GOPATH/src/sigs.k8s.io +git clone https://github.com/kubernetes-sigs/gateway-api +cd gateway-api +``` + +This project works with Go modules; you can choose to setup your environment +outside $GOPATH as well. + + +### Build the Code + +The project uses `make` to drive the build. `make` will run code generators, and +run static analysis against the code and generate Kubernetes CRDs. You can kick +off an overall build from the top-level makefile: + +```shell +make generate +``` + + +#### Add Experimental Fields + +All additions to the API must start in the Experimental release channel. +Experimental fields must be marked with the `` annotation +in Go type definitions. Gateway API CRD generation will only include these +fields in the experimental set of CRDs. + +If experimental fields are removed or renamed, the original field name should be +removed from the go struct, with a tombstone comment +([example](https://github.com/kubernetes/kubernetes/blob/707b8b6efd1691b84095c9f995f2c259244e276c/staging/src/k8s.io/api/core/v1/types.go#L4444-L4445)) +ensuring the field name will not be reused. + +### Deploy the Code + +Use the following command to deploy CRDs to the preexisting `Kind` cluster. + +```shell +make crd +``` + +Use the following command to check if the CRDs have been deployed. + +```shell +kubectl get crds +``` + +### Test Manually + +Install a [gateway API implementation](../implementations.md) and test out the change. Take a look at some +[examples](../guides/index.md). + +### Verify + +Make sure you run the static analysis over the repo before submitting your +changes. The [Prow presubmit][prow-setup] will not let your change merge if +verification fails. + +```shell +make verify +``` + +[prow-setup]: https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes-sigs/gateway-api + + +## Post-Development: Pull Request, Documentation, and more Tests +### Submit a Pull Request + +Gateway API follows a similar pull request process as +[Kubernetes](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md). +Merging a pull request requires the following steps to be completed before the +pull request will be merged automatically. + +- [Sign the CLA](https://git.k8s.io/community/CLA.md) (prerequisite) +- [Open a pull request](https://help.github.com/articles/about-pull-requests/) +- Pass [verification](#verify) tests +- Get all necessary approvals from reviewers and code owners + + +### Documentation + +The site documentation is written in Markdown and compiled with +[mkdocs](https://www.mkdocs.org/). Each PR will automatically include a +[Netlify](https://netlify.com/) deploy preview. When new code merges, it will +automatically be deployed with Netlify to +[gateway-api.sigs.k8s.io](). If you want to +manually preview docs changes locally, you can install mkdocs and run: + +```shell + make docs +``` + +To make it easier to use the right version of mkdocs, there is a `.venv` +target to create a Python virtualenv that includes mkdocs. To use the +mkdocs live preview server while you edit, you can run mkdocs from +the virtualenv: + +```shell +$ make .venv +Creating a virtualenv in .venv... OK +To enter the virtualenv type "source .venv/bin/activate", to exit type "deactivate" +(.venv) $ source .venv/bin/activate +(.venv) $ mkdocs serve +INFO - Building documentation... +... +``` + +For more information on how documentation should be written, refer to our +[Documentation Style Guide](style-guide.md). + +### Conformance Tests + +To develop or run conformance tests, refer to the [Conformance Test +Documentation](../concepts/conformance.md#running-tests). diff --git a/site-src/ko/contributing/enhancement-requests.md b/site-src/ko/contributing/enhancement-requests.md new file mode 100644 index 0000000000..0bdf2ea9f2 --- /dev/null +++ b/site-src/ko/contributing/enhancement-requests.md @@ -0,0 +1,75 @@ +# Enhancement Requests + +Inspired by [Kubernetes enhancements][enhance], Gateway API provides a process for +introducing new functionality or considerable changes to the project. The +enhancement process will evolve over time as the project matures. + +[enhance]: https://github.com/kubernetes/enhancements + +Enhancements provides the basis of a community roadmap. Enhancements may be +filed by anyone, but require approval from a maintainer to accept the +enhancement into the project. + +## What is Considered an Enhancement? + +An enhancement is generally anything that: + +- Introduces changes to an API. +- Needs significant effort to implement. +- Requires documentation to utilize. +- Impacts how a system is operated including addition or removal of significant + capabilities. + +It is unlikely to require an enhancement if it: + +- Fixes a bug +- Adds more testing +- Code refactors + +If you're unsure the proposed work requires an enhancement, file an issue +and ask. + +## New Enhancement Process + +The process for creating new enhancement proposals is documented on the +[GEP Overview][gep] page. Please see that page for all the details about how +to log a new GEP, and the process it will follow on its journey towards +Completed status. + +A **documented** discussion of some form **must** exist prior to submitting a +request for enhancement if that enhancement is non-trivial (which we will define +as either: _implicates changes to the API specification_ +OR _has some kind of end-user impact_). + +Please use our [GitHub Discussions][discussion] forum as the initial place to +start, and feel free to bring that discussion up for synchronous conversation in +one of our [community meetings][meetings]. If the created request doesn't +include reference to a discussion and/or recordings of discussion in our +community meetings, please note that it _may_ get closed with a request to +create an initial discussion first. + +[gep]: ../geps/overview.md +[discussion]: https://github.com/kubernetes-sigs/gateway-api/discussions/new/choose +[meetings]: index.md#meetings + +## When are Enhancements Accepted? + +Gateway API has a predictable release cycle that includes multiple phases. New +enhancements are only considered in the early phases of that release cycle while +the scope of a release is being determined. For more information, refer to our +[release cycle documentation](release-cycle.md). + +## Why are Enhancements Tracked + +As the project evolves, it's important that the community understands how the +enhancement affects the project. Individually, it's hard to understand how all +parts of the system interact, but as a community we can work together to build +the right design and approach before getting too deep into an implementation. + +## When to Comment on an Enhancement Issue + +Please comment on the enhancement issue to: + +- Request a review or clarification on the process +- Update status of the enhancement effort +- Link to relevant issues in other repos diff --git a/site-src/ko/contributing/index.md b/site-src/ko/contributing/index.md new file mode 100644 index 0000000000..613b15decc --- /dev/null +++ b/site-src/ko/contributing/index.md @@ -0,0 +1,123 @@ +# How to Get Involved + +This page contains links to all of the meeting notes, design docs and related +discussions around the APIs. If you're interested in working towards a formal +role in the project, refer to the [Contributor +Ladder](contributor-ladder.md). + +## Feedback and Questions + +For general feedback, questions or to share ideas please feel free to [create a +new discussion][gh-disc]. + +[gh-disc]:https://github.com/kubernetes-sigs/gateway-api/discussions/new + +## Bug Reports + +Bug reports should be filed as [GitHub Issues][gh-issues] on this repo. + +**NOTE**: If you're reporting a bug that applies to a specific implementation of +Gateway API and not the API specification itself, please check our +[implementations page][implementations] to find links to the repositories where +you can get help with your specific implementation. + +[gh-issues]: https://github.com/kubernetes-sigs/gateway-api/issues/new/choose +[implementations]:../implementations.md + +## Communications + +Major discussions and notifications will be sent on the [SIG-NETWORK mailing +list][signetg]. + +We also have a [Slack channel (sig-network-gateway-api)][slack] on k8s.io for day-to-day +questions, discussions. + +[signetg]: https://groups.google.com/forum/#!forum/kubernetes-sig-network +[slack]: https://kubernetes.slack.com/archives/CR0H13KGA + +## Meetings + +Gateway API community meetings happen on the first Tuesday of each month at +8am Pacific Time (15:00 UTC, [convert to your timezone][8am-pst-convert]) and +weekly on all subsequent weeks each month on Mondays at 3pm Pacific Time +(23:00 UTC, [convert to your timezone][3pm-pst-convert]): + +Being the main meeting for Gateway API, the topics can vary here and often this +is where new topics and ideas are discussed, including both ingress and service +mesh use cases. Meetings will be moderated by the [Gateway API maintainers][maintainers] +with notes taken by a volunteer. + +* [Zoom link](https://zoom.us/j/441530404) (passcode in [meeting notes] doc) +* [Add to your calendar](https://calendar.google.com/calendar/u/0/r?cid=88fe1l3qfn2b6r11k8um5am76c@group.calendar.google.com) + +[8am-pst-convert]: http://www.thetimezoneconverter.com/?t=08:00&tz=PT%20%28Pacific%20Time%29 +[3pm-pst-convert]: http://www.thetimezoneconverter.com/?t=15:00&tz=PT%20%28Pacific%20Time%29 +[maintainers]:https://github.com/kubernetes-sigs/gateway-api/blob/main/OWNERS_ALIASES#L12 + +The calendar includes _all_ SIG Network meetings (which therefore includes all +Gateway API meetings, in addition to other subgroup meetings). + + + +### Meeting Notes and Recordings + +Meeting agendas and notes are maintained in the [meeting notes] doc. Feel free +to add topics for discussion at an upcoming meeting. + +All meetings are recorded and automatically uploaded to the +[Gateway API meetings YouTube playlist][gateway-api-yt-playlist]. + +[meeting notes]: https://docs.google.com/document/d/1eg-YjOHaQ7UD28htdNxBR3zufebozXKyI28cl2E11tU/edit +[gateway-api-yt-playlist]: https://www.youtube.com/playlist?list=PL69nYSiGNLP1GgO7k02ipPGZUFpSzGaHH + +#### Early Meetings + +Some early community meetings were uploaded to a [separate YouTube +playlist][early-yt-playlist], and then to the [SIG Network YouTube playlist][sig-net-yt-playlist]. + +Meeting notes for early [GAMMA][gamma] meetings focused on Gateway API for +service mesh use cases can be found in a separate +[meeting notes doc][gamma-meeting-notes]. + +[early-yt-playlist]: https://www.youtube.com/playlist?list=PL7KjrPTDcs4Xe6SZj-51WvBfufKf-la1O +[sig-net-yt-playlist]: https://www.youtube.com/playlist?list=PL69nYSiGNLP2E8vmnqo5MwPOY25sDWIxb +[gamma]: ../mesh/gamma.md +[gamma-meeting-notes]: https://docs.google.com/document/d/1s5hQU0CB9ehjFukRmRHQ41f1FA8GX5_1Rv6nHW6NWAA/edit# + +#### Initial Design Discussions + +* [Kubecon 2019 San Diego: API evolution design discussion][kubecon-2019-na-design-discussion] +* [SIG-NETWORK: Ingress Evolution Sync][sig-net-2019-11-sync] +* [Kubecon 2019 Barcelona: SIG-NETWORK discussion (general topics, includes V2)][kubecon-2019-eu-discussion] + +[kubecon-2019-na-design-discussion]: https://docs.google.com/document/d/1l_SsVPLMBZ7lm_T4u7ZDBceTTUY71-iEQUPWeOdTAxM/preview +[kubecon-2019-eu-discussion]: https://docs.google.com/document/d/1n8AaDiPXyZHTosm1dscWhzpbcZklP3vd11fA6L6ajlY/preview +[sig-net-2019-11-sync]: https://docs.google.com/document/d/1AqBaxNX0uS0fb_fSpVL9c8TmaSP7RYkWO8U_SdJH67k/preview + +## Presentations and Talks + +| Date | Title | | +|----------------|-------|----| +| November, 2019 | [Kubecon 2019 San Diego: Evolving the Kubernetes Ingress APIs to GA and Beyond][2019-kubecon-na-slides] | [slides][2019-kubecon-na-slides], [video][2019-kubecon-na-video]| +| November, 2019 | Kubecon 2019 San Diego: SIG-NETWORK Service/Ingress Evolution Discussion | [slides][2019-kubecon-na-community-slides] | +| May, 2019 | [Kubecon 2019 Barcelona: Ingress V2 and Multicluster Services][2019-kubecon-eu] | [slides][2019-kubecon-eu-slides], [video][2019-kubecon-eu-video]| +| March, 2018 | SIG-NETWORK: Ingress user survey | [data][survey-data], [slides][survey-slides] | + +[2019-kubecon-na]: https://kccncna19.sched.com/event/UaYG/evolving-the-kubernetes-ingress-apis-to-ga-and-beyond-christopher-m-luciano-ibm-bowei-du-google +[2019-kubecon-na-slides]: https://static.sched.com/hosted_files/kccncna19/a5/Kubecon%20San%20Diego%202019%20-%20Evolving%20the%20Kubernetes%20Ingress%20APIs%20to%20GA%20and%20Beyond%20%5BPUBLIC%5D.pdf +[2019-kubecon-na-video]: https://www.youtube.com/watch?v=cduG0FrjdJA +[2019-kubecon-eu]: https://kccnceu19.sched.com/event/MPb6/ingress-v2-and-multicluster-services-rohit-ramkumar-bowei-du-google +[2019-kubecon-eu-slides]: https://static.sched.com/hosted_files/kccnceu19/97/%5Bwith%20speaker%20notes%5D%20Kubecon%20EU%202019_%20Ingress%20V2%20%26%20Multi-Cluster%20Services.pdf +[2019-kubecon-eu-video]: https://www.youtube.com/watch?v=Ne9UJL6irXY&t=1s +[survey-data]: https://github.com/bowei/k8s-ingress-survey-2018 +[survey-slides]: https://github.com/bowei/k8s-ingress-survey-2018/blob/master/survey.pdf +[2019-kubecon-na-community-slides]: https://docs.google.com/presentation/d/1s0scrQCCFLJMVjjGXGQHoV6_4OIZkaIGjwj4wpUUJ7M + +## Code of conduct + +Participation in the Kubernetes community is governed by the [Kubernetes Code of +Conduct](https://github.com/kubernetes/community/blob/master/code-of-conduct.md). diff --git a/site-src/ko/contributing/release-cycle.md b/site-src/ko/contributing/release-cycle.md new file mode 100644 index 0000000000..43a811dfff --- /dev/null +++ b/site-src/ko/contributing/release-cycle.md @@ -0,0 +1,104 @@ +# Release Cycle + +In Gateway API 1.2+, we will be following a more structured and predictable +release cycle that is inspired by the [upstream Kubernetes release +cycle](https://kubernetes.io/releases/release/). + +## Goals + +* Ensure a predictable release schedule that enables 2-3 releases a year +* Minimize the amount of time required from upstream API approvers and make it + more predictable +* Avoid last minute additions to the scope of a release +* Prevent experimental channel from growing by requiring GEPs to leave or + graduate before new ones can be added +* Ensure that SIG-Network TLs are in the loop throughout the process, and have a + meaningful opportunity to review changes before a release +* Provide more advance notice to everyone (SIG-Network TLs, Docs Reviewers, + Implementations, etc) + +## Phases + +### 1. Scoping + +**Timeline:** 4-6 weeks + +In this phase, the Gateway API maintainers and community will be responsible +for determining the set of features we want to include in the release. Although +we can always lessen scope after this point, we will avoid expanding the scope +of the release at a later point unless it is absolutely necessary (critical flaw +in design, security issue, etc). + +A key guideline in this phase is that we want to avoid expanding the size of the +Experimental release channel. That means that each new experimental feature +should be accompanied by the graduation or removal of an enhancement that is +already in the Experimental channel. + +Note that in many cases, this scoping work will require some initial work on +GEPs to determine their viability before committing to including them in a +release. + +### 2. GEP Iteration and Review + +**Timeline:** 5-7 weeks + +In this phase, the Gateway API community will work to update GEPs and meet +graduation criteria for each feature that has been deemed in scope for the +release cycle. As we’re working on new features, we will bring these discussions +to the broader SIG-Network meetings for feedback throughout our development +process. If a GEP has not merged with the target status by the end of this +phase, it will be pulled from the scope of the release. + +### 3. API Refinement and Documentation + +**Timeline:** 3-5 weeks + +This phase is entirely focused on translating the concepts defined in the GEP +(previous phase) into both API specification and documentation. This offers one +final chance for the Gateway API community to refine the details that have +already been agreed to in the GEP, but any modifications at this stage should be +minor. If either documentation or API Spec have not merged by the end of this +phase, this enhancement will be pulled from the scope of the release. + +### 4. SIG-Network Review and Release Candidates + +**Timeline:** 2-4 weeks + +This phase officially begins with the review session scheduled with SIG-Network +TLs several weeks earlier in phase 3. In that review session, Gateway API +maintainers and SIG-Network TLs should reach an agreement on the following: + +1. Any blockers for an initial release candidate +1. How much time, if any, SIG-Network TLs want to review any changes in this + release +1. A time after which we can assume lazy consensus and move on with the final + release of the API + +In general, we expect each minor release to be preceded by two release +candidates. These release candidates will enable implementations to test against +our release, work out any bugs, and gather early feedback on the viability of +the release. + +## Contributions Welcome in Each Phase + +The following table illustrates when different kinds of contributions will be +welcome. There will be some exceptions to this, but it should be useful as an +overall guideline: + +| | 1. Scope | 2. GEP | 3. API | 4. Review | +| - | :-: | :-: | :-:| :-: | +| New GEPs | ✅ | ❌ | ❌ | ❌ | +| Major GEP Updates | ✅ | ✅ | ❌ | ❌ | +| GEP Refinement | ✅ | ✅ | ✅ | ❌ | +| API Spec Additions | ❌ | ❌ | ✅ | ❌ | +| New Conformance Tests | ✅ | ✅ | ✅ | ❌ | +| Bug Fixes | ✅ | ✅ | ✅ | ✅ | +| Documentation | ✅ | ✅ | ✅ | ✅ | +| Review | ✅ | ✅ | ✅ | ✅ | + +## Timeline + +Given the above, we expect each release to take 14-22 weeks (4-5 months). At +least initially, Gateway API maintainers will set end dates for each phase as we +are beginning the phase. In future releases, we may choose to set all dates for +the release in advance. diff --git a/site-src/ko/contributing/style-guide.md b/site-src/ko/contributing/style-guide.md new file mode 100644 index 0000000000..3358e03239 --- /dev/null +++ b/site-src/ko/contributing/style-guide.md @@ -0,0 +1,48 @@ +# Documentation Style Guide + +Gateway API aims to adhere to the upstream [Kubernetes Documentation Style +Guide](https://kubernetes.io/docs/contribute/style/style-guide/) wherever +possible. This guide should be considered an extension of that guide. Whenever +there is conflicting guidance, the information contained in this guide has +precedence for Gateway API documentation. + +## Name of the Project +This project is named "Gateway API", not "the Gateway API". As such, the only +time it is acceptable to use "the Gateway API" is when it is part of a broader +term, such as "the Gateway API maintainers". + +## Callouts +To implement callouts in documentation, we make use of [mkdocs-material +admonitions](https://squidfunk.github.io/mkdocs-material/reference/admonitions/). + +### Release Channels +Wherever possible, we try to clearly state which release channel a resource or +feature is currently included in, and which version it was introduced to that +channel. To accomplish that, we use admonitions that look like this: + +??? success "Standard Channel since v0.5.0" + + The `HTTPRoute` resource is GA and has been part of the Standard Channel + since `v0.5.0`. For more information on release channels, refer to our + [versioning guide](../concepts/versioning.md). + +??? example "Experimental Channel since v0.3.0" + + The `TLSRoute` resource is Alpha and has been part of the Experimental + Channel since `v0.3.0`. For more information on release channels, refer to + our [versioning guide](../concepts/versioning.md). + +## Diagrams +In many cases, diagrams are the best way to explain a concept. Unfortunately +they can be hard to maintain and update. To ensure diagrams are more +maintainable, we strongly recommend using the built-in support for +[Mermaid](https://mermaid.js.org/) diagrams. Here is a simple example of a +diagram: + +```mermaid +flowchart TD + Start --> Stop +``` + +Whenever it's not practical to use Mermaid diagrams, we ask that you link to +a source that enables anyone to make a copy and edit as needed. diff --git a/site-src/ko/faq.md b/site-src/ko/faq.md new file mode 100644 index 0000000000..79b09ba0ef --- /dev/null +++ b/site-src/ko/faq.md @@ -0,0 +1,88 @@ +# 자주 묻는 질문 (FAQ) + +#### 게이트웨이 API에 어떻게 참여할 수 있나? + +[커뮤니티](contributing/index.md) 페이지에서 프로젝트에 참여하는 방법을 +확인할 수 있다. + +#### 게이트웨이 API가 인그레스 API를 대체할 것인가? +아니다. 인그레스 API는 쿠버네티스 1.19부터 GA이다. +이 API를 사용 중단 할 계획은 없으며 대부분의 인그레스 컨트롤러가 이를 무기한 지원할 것으로 예상한다. + +#### 인그레스와 게이트웨이 API의 차이점은 무엇인가? +인그레스는 주로 간단하고 선언적인 구문으로 HTTP 애플리케이션 노출을 대상으로 한다. +게이트웨이 API는 HTTP뿐만 아니라 더 많은 프로토콜에 사용할 수 있는 더 일반적인 프록시 API를 노출하며, +더 많은 인프라 구성 요소를 모델링하여 클러스터 운영자에게 +더 나은 배포 및 관리 옵션을 제공한다. + +자세한 정보는 [인그레스에서 마이그레이션](guides/migrating-from-ingress.md) +가이드를 참조하자. + +#### 기본 컨트롤러 구현이 있을 것인가? +없다. +이미 선택할 수 있는 많은 훌륭한 [구현체](implementations.md)들이 있다. +이 프로젝트의 범위는 API, 호환성 테스트 및 전체 문서를 정의하는 것이다. + +#### 게이트웨이 API를 통해 사용자 정의 기능을 어떻게 노출할 수 있는가? +구현별 기능으로 API를 확장하는 데 사용할 수 있는 몇 가지 +메커니즘이 있다. + +* [정책 연결](reference/policy-attachment.md) 모델을 사용하면 +게이트웨이 API 객체를 구현별 CRD로 꾸릴 수 있다. +정책이나 구성 객체는 이름으로 또는 명시적 객체 참조를 사용하여 +게이트웨이 API 객체와 일치할 수 있다. + +* 게이트웨이 API 리소스의 문자열 필드에 구현별 값을 사용한다. + +* 최후의 수단으로 게이트웨이 API 객체에 구현별 어노테이션을 + 사용한다. + +* API 정의 확장 지점을 사용한다. + 일부 게이트웨이 API 객체에는 구현이 사용할 수 있는 명시적 + [확장 지점](concepts/api-overview.md#extension-points)이 있다. + +#### 게이트웨이 API 릴리스는 어디서 찾을 수 있나? +게이트웨이 API 릴리스는 +[GitHub 저장소](https://github.com/kubernetes-sigs/gateway-api)의 태그이다. +[GitHub 릴리스](https://github.com/kubernetes-sigs/gateway-api/releases) 페이지에서 +모든 릴리스를 볼 수 있다. + +#### 알파 API 버전에 대해 어떻게 생각해야 하나? +업스트림 쿠버네티스와 유사하게 알파 API 버전은 리소스가 여전히 실험적 성격이며 +게이트웨이 API의 향후 릴리스에서 제거되거나 호환되지 않는 방식으로 변경될 수 있음을 +나타낸다. + +자세한 정보는 [버전 관리](concepts/versioning.md) 문서를 참조하라. + +#### 어떤 쿠버네티스 버전이 지원되는가? +[지원 버전](concepts/versioning.md#supported-versions)에 대한 정책을 +참조하자. + +#### SSL 패스스루가 지원되나? +SSL 패스스루 +(게이트웨이가 [전송 계층 보안(TLS)](https://en.wikipedia.org/wiki/Transport_Layer_Security) 암호화를 종료하는 대신 _그대로_ 백엔드 서비스로 라우팅하는 것) +는 +[TLSRoute](concepts/api-overview.md#tlsroute)에서 지원된다. +패스스루 및 기타 TLS 구성에 대한 자세한 내용은 +[TLS 가이드](guides/tls.md)를 참조하자. + +#### 게이트웨이 API와 API 게이트웨이의 차이점은 무엇인가? +[API 게이트웨이](https://glossary.cncf.io/api-gateway/)는 +고유한 애플리케이션 API를 집계하여 한 곳에서 모두 사용 가능하게 만드는 도구이다. +이를 통해 조직은 인증, 권한 부여 또는 애플리케이션 간 요청 수 제한과 같은 핵심 +기능을 중앙에서 관리할 수 있다. +API 게이트웨이는 (종종 외부) API 소비자를 위한 공통 인터페이스로 기능한다. + +게이트웨이 API는 쿠버네티스에서 서비스 네트워킹을 모델링하는 쿠버네티스 리소스 집합으로 정의된 인터페이스이다. +주요 리소스 중 하나는 `게이트웨이`로, 인스턴스화할 게이트웨이 타입(또는 클래스)과 그 구성을 선언한다. +게이트웨이 제공자로서 게이트웨이 API를 구현하여 +쿠버네티스 서비스 네트워킹을 표현력 있고 확장 가능하며 역할 지향적인 방식으로 모델링할 수 +있다. + +일부 API 게이트웨이는 게이트웨이 API를 사용하여 프로그래밍할 수 있다. + +#### 게이트웨이 API가 API 관리의 표준인가? +아니다. +API 관리는 게이트웨이 API가 목표로 하는 것이나 API 게이트웨이가 제공하려는 것보다 훨씬 광범위한 개념이다. +API 게이트웨이는 API 관리 솔루션의 필수 부분이 될 수 있다. +게이트웨이 API는 API 게이트웨이 프로비저닝을 표준화하는 방법으로 볼 수 있다. diff --git a/site-src/ko/geps/gep-1016/index.md b/site-src/ko/geps/gep-1016/index.md new file mode 100644 index 0000000000..e232d2aa17 --- /dev/null +++ b/site-src/ko/geps/gep-1016/index.md @@ -0,0 +1,710 @@ +# GEP-1016: GRPCRoute + +* Issue: [#1016](https://github.com/kubernetes-sigs/gateway-api/issues/1016) +* Status: Standard + +> **Note**: This GEP is exempt from the [Probationary Period][expprob] rules of +> our GEP overview as it existed before those rules did, and so it has been +> explicitly grandfathered in. + +[expprob]:../overview.md#probationary-period + +## Goal + +Add an idiomatic GRPCRoute for routing gRPC traffic. + +## Non-Goals + +While certain gRPC implementations support multiple transports and multiple +interface definition languages (IDLs), this proposal limits itself to +[HTTP/2](https://developers.google.com/web/fundamentals/performance/http2) as +the transport and [Protocol Buffers](https://developers.google.com/protocol-buffers) +as the IDL, which makes up the vast majority of gRPC traffic in the wild. + +## Introduction + +While it would be possible to support gRPC via custom, out-of-tree CRDs, in the long run, this would +lead to a fragmented ecosystem. + +gRPC is a [popular RPC framework adopted widely across the industry](https://grpc.io/about/#whos-using-grpc-and-why). +The protocol is used pervasively within the Kubernetes project itself as the basis for +many interfaces, including: + +- [the CSI](https://github.com/container-storage-interface/spec/blob/5b0d4540158a260cb3347ef1c87ede8600afb9bf/spec.md), +- [the CRI](https://github.com/kubernetes/cri-api/blob/49fe8b135f4556ea603b1b49470f8365b62f808e/README.md), +- [the device plugin framework](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/) + +Given gRPC's importance in the application-layer networking space and to +the Kubernetes project in particular, we must ensure that the gRPC control plane +configuration landscape does not Balkanize. + +### Encapsulated Network Protocols + +It is theoretically possible to route gRPC traffic using only `HTTPRoute` +resources, but there are several serious problems with forcing gRPC users to route traffic at +the level of HTTP. This is why we propose a new resource. + +In setting this precedent, we must also introduce a coherent policy for _when_ +to introduce a custom `Route` resource for an encapsulated protocol for which a +lower layer protocol already exists. We propose the following criteria for such +an addition. + +- Users of the encapsulated protocol would miss out on significant conventional features from their ecosystem if forced to route at a lower layer. +- Users of the encapsulated protocol would experience a degraded user experience if forced to route at a lower layer. +- The encapsulated protocol has a significant user base, particularly in the Kubernetes community. + +gRPC meets _all_ of these criteria and is therefore, we contend, a strong +candidate for inclusion in the Gateway API. + +#### HTTP/2 Cleartext + +gRPC allows HTTP/2 cleartext communication (H2C). This is conventionally deployed for +testing. Many control plane implementations do not support this by default and +would require special configuration to work properly. + +#### Content-Based Routing + +While not included in the scope of this initial GEP, a common use case cited for +routing gRPC is payload-aware routing. That is, routing rules which determine a +backend based on the contents of the protocol buffer payload. + +#### User Experience + +The user experience would also degrade significantly if forced to route at the level of HTTP. + +- Encoding services and methods as URIs (an implementation detail of gRPC) +- The [Transfer Encoding header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding) for trailers +- Many features supported by HTTP/2 but not by gRPC, such as: + - Query parameters + - Methods besides `POST` + - [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) + + +#### Proxyless Service Mesh + +The gRPC library supports proxyless service mesh, a system by which routing +configuration is received and acted upon not by an in-line proxy or sidecar +proxy but by the client itself. Eventually, `GRPCRoute` in the Gateway API +should support this feature. However, to date, there are no HTTP client +libraries capable of participating in a proxyless service mesh. + +--- + +### Cross Serving + +Occasionally, gRPC users will place gRPC services on the same hostname/port +combination as HTTP services. For example, `foo.com:443/v1` might serve +REST+JSON while `foo.com:443/com.foo.WidgetService/` serves gRPC. Such an +arrangement in the Gateway API poses complex technical challenges. How are +GRPCRoutes to be reconciled with HTTPRoutes? And how should individual +implementations accomplisht this? + +After a long look at the implementations with which the author is familiar, it +was deemed technically infeasible. Furthermore, after surveying the gRPC +community, this was found to be a niche use case to begin with. + +In any case, users wishing to accomplish this always have the option of using +`HTTPRoute` resources to achieve this use case, at the cost of a degraded user +experience. + +If at some point in the future, demand for this use case increases and we have +reason to believe that the feasibility of implementation has improved, this +would be a backward compatible change. + +As such, implementations that support GRPCRoute must enforce uniqueness of +hostnames between `GRPCRoute`s and `HTTPRoute`s. If a route (A) of type `HTTPRoute` or +`GRPCRoute` is attached to a Listener and that listener already has another Route (B) of +the other type attached and the intersection of the hostnames of A and B is +non-empty, then the implementation must reject Route A. That is, the +implementation must raise an 'Accepted' condition with a status of 'False' in +the corresponding RouteParentStatus. + + +## API + +The API deviates from `HTTPRoute` where it results in a better UX for gRPC +users, while mirroring it in all other cases. + +### Example `GRPCRoute` + +```yaml +kind: GRPCRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: foo-grpcroute +spec: + parentRefs: + - name: my-gateway + hostnames: + - foo.com + - bar.com + rules: + - matches: + method: + service: helloworld.Greeter + method: SayHello + headers: + - type: Exact + name: magic + value: foo + + filters: + - type: RequestHeaderModifierFilter + add: + - name: my-header + value: foo + + - type: RequestMirrorPolicyFilter + destination: + backendRef: + name: mirror-svc + + backendRefs: + - name: foo-v1 + weight: 90 + - name: foo-v2 + weight: 10 +``` + +#### Method Matchers + +It's been pointed out that the `method` field above stutters. That is, in order +to specify a method matcher, one must type the string `method` twice in a row. +This is an artifact of less-than-clear nomenclature within gRPC. There +_are_ alternatives for the naming here, but none of them would actually be an +improvement on the stutter. Consider the following URI: + +`/foo.bar.v1.WidgetService/GetWidget` + +- `/foo.bar.v1.WidgetService/GetWidget` is called the method or, less commonly, the _full_ method. +- `foo.bar.v1.WidgetService` is called the service or, less commonly, the _full_ service (since `WidgetService` can reasonably be called the service)] +- `GetWidget` is called the method. + +These terms _could_ be added in, but these names are found almost exclusively +within the various gRPC implementations. And inconsistently across those +implementations. + +Therefore, we opt for the stutter over any of the longer names outlined above. + +#### Matcher Types + +`GRPCRoute` method matchers admits two types: `Exact` and `RegularExpression`. +If not specified, the match will be treated as type `Exact`. Method matchers +will act _as if_ a URI match had been used. A full matrix of equivalent behavior +is provided below: + +##### Type Exact + +|Service|Method|URI Matcher| +|----------|----------|-----------| +|Specified|Specified|Exact `/${SERVICE}/${METHOD}`| +|Specified|Unspecified|Prefix `/${SERVICE}/`| +|Unspecified|Specified|Suffix `/${METHOD}/` or Regex `/.+/${METHOD}`| +|Unspecified|Unspecified|Not allowed| + +##### Type RegularExpression + +|Service|Method|URI Matcher| +|----------|----------|-----------| +|Specified|Specified|Regex `/${SERVICE}/${METHOD}`| +|Specified|Unspecified|Regex `/${SERVICE}/.+`| +|Unspecified|Specified|Regex `/.+/${METHOD}`| +|Unspecified|Unspecified|Prefix `/`| + +##### Method specified but not Service + +In the table above, `Service` unspecified and `Method` specified with type Exact +is listed as being equivalent to a path matcher with type suffix or type regex. +We imagine that many GRPCRoute implementations will be done using translation to +`HTTPRoute`s. `HTTPRoute` does not support a Suffix matcher and its Regex +matcher is specified as "Implementation-specific" support. In order to accommodate +`GRPCRoute` implementations built on top of `HTTPRoute` implementations without +regex support, we list this particular case as having implementation-specific +support within the context of `GRPCRoute`. + +#### Transport + +No new `ProtocolType` will be added. While gRPC _does_ have some special +HTTP usage (HTTP/2 cleartext and HTTP/2 without an upgrade from HTTP/1.1), +`GRPCRoute` will be used in conjunction with the existing `HTTP` and `HTTPS` +ProtocolTypes. + +Implementations supporting `GRPCRoute` with the `HTTPS` `ProtocolType` must +accept HTTP/2 connections without an [initial upgrade from HTTP/1.1](https://datatracker.ietf.org/doc/html/rfc7230#section-6.7). If the +implementation does not support this, then it should raise a "Detached" +condition for the affected listener with a reason of "UnsupportedProtocol" + +Implementations supporting `GRPCRoute` with the `HTTP` `ProtocolType` must +support cleartext HTTP/2 connections without an [initial upgrade from HTTP/1.1](https://datatracker.ietf.org/doc/html/rfc7230#section-6.7). If the implementation does not support this, then it +should raise a "Detached" condition for the affected listener with a reason of +"UnsupportedProtocol" + + +### Structs + +{% raw%} +```go +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:printcolumn:name="Hostnames",type=string,JSONPath=`.spec.hostnames` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// GRPCRoute provides a way to route gRPC requests. This includes the capability +// to match requests by hostname, gRPC service, gRPC method, or HTTP/2 header. Filters can be +// used to specify additional processing steps. Backends specify where matching +// requests should be routed. +// +// Implementations supporting `GRPCRoute` with the `HTTPS` `ProtocolType` must +// accept HTTP/2 connections without an initial upgrade from HTTP/1.1. If the +// implementation does not support this, then it should raise a "Detached" +// condition for the affected listener with a reason of "UnsupportedProtocol" +// +// Implementations supporting `GRPCRoute` with the `HTTP` `ProtocolType` must +// support cleartext HTTP/2 without an initial upgrade from HTTP/1.1. If the +// implementation does not support this, then it should raise a "Detached" +// condition for the affected listener with a reason of "UnsupportedProtocol" +// +// Support: Extended +type GRPCRoute struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of GRPCRoute. + Spec GRPCRouteSpec `json:"spec,omitempty"` + + // Status defines the current state of GRPCRoute. + Status GRPCRouteStatus `json:"status,omitempty"` +} + +// GRPCRouteStatus defines the observed state of GRPCRoute. +type GRPCRouteStatus struct { + RouteStatus `json:",inline"` +} + +// GRPCRouteSpec defines the desired state of GRPCRoute +type GRPCRouteSpec struct { + CommonRouteSpec `json:",inline"` + + // Hostnames defines a set of hostname that should match against the GRPC + // Host header to select a GRPCRoute to process the request. This matches + // the RFC 1123 definition of a hostname with 2 notable exceptions: + // + // 1. IPs are not allowed. + // 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + // label must appear by itself as the first label. + // + // If a hostname is specified by both the Listener and GRPCRoute, there + // must be at least one intersecting hostname for the GRPCRoute to be + // attached to the Listener. For example: + // + // * A Listener with `test.example.com` as the hostname matches GRPCRoutes + // that have either not specified any hostnames, or have specified at + // least one of `test.example.com` or `*.example.com`. + // * A Listener with `*.example.com` as the hostname matches GRPCRoutes + // that have either not specified any hostnames or have specified at least + // one hostname that matches the Listener hostname. For example, + // `test.example.com` and `*.example.com` would both match. On the other + // hand, `example.com` and `test.example.net` would not match. + // + // If both the Listener and GRPCRoute have specified hostnames, any + // GRPCRoute hostnames that do not match the Listener hostname MUST be + // ignored. For example, if a Listener specified `*.example.com`, and the + // GRPCRoute specified `test.example.com` and `test.example.net`, + // `test.example.net` must not be considered for a match. + // + // If both the Listener and GRPCRoute have specified hostnames, and none + // match with the criteria above, then the GRPCRoute is not accepted. The + // implementation must raise an 'Accepted' Condition with a status of + // `False` in the corresponding RouteParentStatus. + // + // If a Route (A) of type HTTPRoute or GRPCRoute is attached to a + // Listener and that listener already has another Route (B) of the other + // type attached and the intersection of the hostnames of A and B is + // non-empty, then the implementation must reject Route A. That is, the + // implementation must raise an 'Accepted' condition with a status of + // 'False' in the corresponding RouteParentStatus. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Hostnames []Hostname `json:"hostnames,omitempty"` + + // Rules are a list of GRPC matchers, filters and actions. + // + // +optional + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:default={{matches: {{method: {type: "Exact"}}}}} + Rules []GRPCRouteRule `json:"rules,omitempty"` +} + +// GRPCRouteRule defines semantics for matching an gRPC request based on +// conditions (matches), processing it (filters), and forwarding the request to +// an API object (backendRefs). +type GRPCRouteRule struct { + // Matches define conditions used for matching the rule against incoming + // gRPC requests. Each match is independent, i.e. this rule will be matched + // if **any** one of the matches is satisfied. + // + // For example, take the following matches configuration: + // + // ``` + // matches: + // - method: + // service: foo.bar + // headers: + // values: + // version: 2 + // - method: + // service: foo.bar.v2 + // ``` + // + // For a request to match against this rule, a request should satisfy + // EITHER of the two conditions: + // + // - service of foo.bar AND contains the header `version: 2` + // - service of foo.bar.v2 + // + // See the documentation for GRPCRouteMatch on how to specify multiple + // match conditions that should be ANDed together. + // + // If no matches are specified, the implementation must match every gRPC request. + // + // Proxy or Load Balancer routing configuration generated from GRPCRoutes + // MUST prioritize rules based on the following criteria, continuing on + // ties. Merging must not be done between GRPCRoutes and HTTPRoutes. + // Precedence must be given to the rule with the largest number of: + // + // * Characters in a matching non-wildcard hostname. + // * Characters in a matching hostname. + // * Characters in a matching service. + // * Characters in a matching method. + // * Header matches. + // + // If ties still exist across multiple Routes, matching precedence MUST be + // determined in order of the following criteria, continuing on ties: + // + // * The oldest Route based on creation timestamp. + // * The Route appearing first in alphabetical order by + // "{namespace}/{name}". + // + // If ties still exist within the Route that has been given precedence, + // matching precedence MUST be granted to the first matching rule meeting + // the above criteria. + // + // +optional + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{method: {type: "Exact"}}} + Matches []GRPCRouteMatch `json:"matches,omitempty"` + + // Filters define the filters that are applied to requests that match + // this rule. + // + // The effects of ordering of multiple behaviors are currently unspecified. + // This can change in the future based on feedback during the alpha stage. + // + // Conformance-levels at this level are defined based on the type of filter: + // + // - ALL core filters MUST be supported by all implementations. + // - Implementers are encouraged to support extended filters. + // - Implementation-specific custom filters have no API guarantees across + // implementations. + // + // Specifying a core filter multiple times has unspecified or + // implementation-specific conformance. + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Filters []GRPCRouteFilter `json:"filters,omitempty"` + + // BackendRefs defines the backend(s) where matching requests should be + // sent. + + // If unspecified or invalid (refers to a nonexistent resource or a Service + // with no endpoints), the rule performs no forwarding. If there are also no + // filters specified that would result in a response being sent, a gRPC `UNAVAILABLE` + // status is returned. `UNAVAILABLE` responses must be sent so that the overall + // weight is respected; if an invalid backend is requested to have 80% of + // requests, then 80% of requests must get a `UNAVAILABLE` instead. + // Support: Core for Kubernetes Service + // Support: Implementation-specific for any other resource + // + // Support for weight: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + BackendRefs []GRPCBackendRef `json:"backendRefs,omitempty"` +} + +// GRPCRouteMatch defines the predicate used to match requests to a given +// action. Multiple match types are ANDed together, i.e. the match will +// evaluate to true only if all conditions are satisfied. +// +// For example, the match below will match a gRPC request only if its service +// is `foo` AND it contains the `version: v1` header: +// +// ``` +// match: +// method: +// type: Exact +// service: "foo" +// headers: +// - name: "version" +// value "v1" +// ``` +type GRPCRouteMatch struct { + // Path specifies a gRPC request service/method matcher. If this field is not + // specified, all services and methods will match. + // + // +optional + // +kubebuilder:default={type: "Exact"} + Method *GRPCMethodMatch `json:"path,omitempty"` + + // Headers specifies gRPC request header matchers. Multiple match values are + // ANDed together, meaning, a request must match all the specified headers + // to select the route. + // + // +listType=map + // +listMapKey=name + // +optional + // +kubebuilder:validation:MaxItems=16 + Headers []GRPCHeaderMatch `json:"headers,omitempty"` +} + +// GRPCPathMatch describes how to select a gRPC route by matching the gRPC +// request service and/or method.. +// +// At least one of Service and Method must be a non-empty string. +type GRPCMethodMatch struct { + // Type specifies how to match against the service and/or method. + // Support: Core (Exact with service and method specified) + // + // Support Implementation-specific (Exact with method specified but no + // service specified) + // + // Support: Implementation-specific (RegularExpression) + // + // +optional + // +kubebuilder:default=Exact + Type *GRPCMethodMatchType `json:"type,omitempty"` + + + // Value of the service to match against. If left empty or omitted, will + // match all services. + // + // At least one of Service and Method must be a non-empty string. + // +optional + // +kubebuilder:default="" + // +kubebuilder:validation:MaxLength=1024 + Service *string `json:"value,omitempty"` + + // Value of the method to match against. If left empty or omitted, will + // match all services. + // + // At least one of Service and Method must be a non-empty string. + // +optional + // +kubebuilder:default="" + // +kubebuilder:validation:MaxLength=1024 + Method *string `json:"value,omitempty"` +} + +// MethodMatchType specifies the semantics of how gRPC methods and services should be compared. +// Valid MethodMatchType values are: +// +// * "Exact" +// * "RegularExpression" +// +// Exact paths must be syntactically valid: +// +// - Must not contain `/` character +// +// +kubebuilder:validation:Enum=Exact;PathPrefix;RegularExpression +// +kubebuilder:validation:Enum=Exact;RegularExpression +type GRPCMethodMatchType string + +const ( + // Matches the service and/or method exactly and with case sensitivity. + PathMatchExact PathMatchType = "Exact" + + // Matches if the service and/or method matches the given regular expression with + // case sensitivity. + // + // Since `"RegularExpression"` has custom conformance, implementations + // can support POSIX, PCRE, RE2 or any other regular expression dialect. + // Please read the implementation's documentation to determine the supported + // dialect. + PathMatchRegularExpression PathMatchType = "RegularExpression" +) + +// GRPCHeaderMatch describes how to select a gRPC route by matching gRPC request +// headers. +type GRPCHeaderMatch struct { + // Type specifies how to match against the value of the header. + // + // +optional + // +kubebuilder:default=Exact + Type *HeaderMatchType `json:"type,omitempty"` + + // Name is the name of the gRPC Header to be matched. + // + // If multiple entries specify equivalent header names, only the first + // entry with an equivalent name MUST be considered for a match. Subsequent + // entries with an equivalent header name MUST be ignored. Due to the + // case-insensitivity of header names, "foo" and "Foo" are considered + // equivalent. + Name HeaderName `json:"name"` + + // Value is the value of the gRPC Header to be matched. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=4096 + Value string `json:"value"` +} + +// +kubebuilder:validation:Enum=Exact;RegularExpression +type HeaderMatchType string + +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=256 +// +kubebuilder:validation:Pattern=`^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$` +type HeaderName string + +// GRPCBackendRef defines how a GRPCRoute should forward a gRPC request. +type GRPCBackendRef struct { + // BackendRef is a reference to a backend to forward matched requests to. + // + // If the referent cannot be found, this GRPCBackendRef is invalid and must + // be dropped from the Gateway. The controller must ensure the + // "ResolvedRefs" condition on the Route is set to `status: False` and not + // configure this backend in the underlying implementation. + // + // If there is a cross-namespace reference to an *existing* object + // that is not covered by a ReferenceGrant, the controller must ensure the + // "ResolvedRefs" condition on the Route is set to `status: False`, + // with the "RefNotPermitted" reason and not configure this backend in the + // underlying implementation. + // + // In either error case, the Message of the `ResolvedRefs` Condition + // should be used to provide more detail about the problem. + // + // Support: Implementation-specific + // + // +optional + BackendRef `json:",inline"` + + // Filters defined at this level should be executed if and only if the + // request is being forwarded to the backend defined here. + // + // Support: Implementation-specific (For broader support of filters, use the Filters field + // in GRPCRouteRule.) + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Filters []GRPCRouteFilter `json:"filters,omitempty"` +} + +// GRPCRouteFilter defines processing steps that must be completed during the +// request or response lifecycle. GRPCRouteFilters are meant as an extension +// point to express processing that may be done in Gateway implementations. Some +// examples include request or response modification, implementing +// authentication strategies, rate-limiting, and traffic shaping. API +// guarantee/conformance is defined based on the type of the filter. +type GRPCRouteFilter struct { + // Type identifies the type of filter to apply. As with other API fields, + // types are classified into three conformance levels: + // + // - Core: Filter types and their corresponding configuration defined by + // "Support: Core" in this package, e.g. "RequestHeaderModifier". All + // implementations must support core filters. + // + // - Extended: Filter types and their corresponding configuration defined by + // "Support: Extended" in this package, e.g. "RequestMirror". Implementers + // are encouraged to support extended filters. + // + // - Custom: Filters that are defined and supported by specific vendors. + // In the future, filters showing convergence in behavior across multiple + // implementations will be considered for inclusion in extended or core + // conformance levels. Filter-specific configuration for such filters + // is specified using the ExtensionRef field. `Type` should be set to + // "ExtensionRef" for custom filters. + // + // Implementers are encouraged to define custom implementation types to + // extend the core API with implementation-specific behavior. + // + // If a reference to a custom filter type cannot be resolved, the filter + // MUST NOT be skipped. Instead, requests that would have been processed by + // that filter MUST receive a HTTP error response. + // + // +unionDiscriminator + // +kubebuilder:validation:Enum=RequestHeaderModifier;RequestMirror;ExtensionRef + // + Type GRPCRouteFilterType `json:"type"` + + // RequestHeaderModifier defines a schema for a filter that modifies request + // headers. + // + // Support: Core + // + // Support: Core + // + // +optional + RequestHeaderModifier *HTTPRequestHeaderFilter `json:"requestHeaderModifier,omitempty"` + + // RequestMirror defines a schema for a filter that mirrors requests. + // Requests are sent to the specified destination, but responses from + // that destination are ignored. + // + // Support: Extended + // + // +optional + RequestMirror *HTTPRequestMirrorFilter `json:"requestMirror,omitempty"` + + // ExtensionRef is an optional, implementation-specific extension to the + // "filter" behavior. For example, resource "myroutefilter" in group + // "networking.example.net"). ExtensionRef MUST NOT be used for core and + // extended filters. + // + // Support: Implementation-specific + // Support: Implementation-specific + // + // +optional + ExtensionRef *LocalObjectReference `json:"extensionRef,omitempty"` +} +``` +{% endraw%} + + + + +## Beta Graduation Criteria + +- `GRPCRoute` has been implemented by at least 2 controllers. +- Conformance tests are in place for the majority of the API surface. +- It is known that users of `GRPCRoute` exist. +- An API review has been performed by upstream Kubernetes reviewers. + +## GA Graduation Criteria + +- `GRPCRoute` has been implemented by at least 4 controllers. +- Exhaustive conformance tests are in place. +- Adoption of `GRPCRoute` has been shown to have expanded beyond its initial set of users. + +## Future Enhancements + +Many more ideas have been discussed for the `GRPCRoute` resource, but in the +interest of keeping this particular proposal tractable, they have been deferred +for future proposals. Enough thought has been given to these use cases at the +moment, however, that all of the following may be added at a later date in a +backward-compatible manner. + +Some of these ideas are: + +- Integration with Service Meshes (both sidecar-proxied and proxyless) +- Better UX for enabling reflection support +- gRPC Web support +- HTTP/JSON transcoding at the gateway +- Protobuf payload-based routing diff --git a/site-src/ko/geps/gep-1016/metadata.yaml b/site-src/ko/geps/gep-1016/metadata.yaml new file mode 100644 index 0000000000..52aa770cfb --- /dev/null +++ b/site-src/ko/geps/gep-1016/metadata.yaml @@ -0,0 +1,8 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1016 +name: GRPCRoute +status: Experimental +authors: + - gnossen + - robscott diff --git a/site-src/ko/geps/gep-1282/index.md b/site-src/ko/geps/gep-1282/index.md new file mode 100644 index 0000000000..f85c3330b4 --- /dev/null +++ b/site-src/ko/geps/gep-1282/index.md @@ -0,0 +1,114 @@ +# GEP-1282: Describing Backend Properties + +* Issue: [#1282](https://github.com/kubernetes-sigs/gateway-api/issues/1282) +* Status: Declined + + +## Explanation for Declined status + +This GEP is declined because, after spending a lot of time discussing it, we felt that it was too large, and had too many crosscutting concerns. + +It's superseded for TLS Backend Properties by [GEP-1897](https://github.com/kubernetes-sigs/gateway-api/issues/1897). + +## TLDR + +End-user feedback of Gateway API has presented a trend: some types of configuration requested by users are more about defining functionality that describes _capabilities of the backend_ more than the _route you take to get to the backend_. + +There is currently nowhere to put these capabilities in the API, so we need to find a place to put the information required to meet these use cases, with the simplest examples being backend TLS or websocket details. + +The purpose of this GEP is to add APIs for capturing those backend capabilities to enable more complex routing composition. + +## Goals + +* Provide a method to store properties and capabilities for service backends as extended-only features +* The method must be structured (that is, stored in a typed schema), and extensible (the design must include ways in which we can add more properties and capabilities in the future without redesigning it). +* The method should have a roadmap where we can take what we learn from this design and bring it to the core Kubernetes resources later. +* Clear separation of concerns with PolicyAttachment for properties which require multiple levels of defaults/overrides (timeouts, retries, etc). + + +## Non-Goals + +* We don’t want to require changes to v1.Service to start with, as the turnaround time for those changes can be years. +* Our solution should not use unstructured data like labels and annotations - these are very sticky and hard to get rid of once you start using them. +* v1.Service’s appProtocol field is not fit for purpose, because it is defined as accepting values either from the [IANA Service Name registry](https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtmly), or domain-prefixed values and we need more flexibility than that. +* To be populated as we discuss more. + + +## Introduction + +As implementations have started to build out HTTPRoute support, requests for some common capabilities have started coming up, particularly TLS re-encryption (encryption between Gateway and backend), Websockets tracking, and HTTP/2 support. + +Evan Anderson opened a [discussion that generated a lot of interest](https://github.com/kubernetes-sigs/gateway-api/discussions/1244), and during that discussion, we brought up a few more points: +* Whatever we do to solve this in the HTTPRoute case may be applicable describing more general service properties, like identity, which could be useful for other Route use cases. +* This may be very useful for mesh/GAMMA use cases as well as more generally for adding arbitrary future capabilities to the backend service. An example is a CA cert for connecting to the backend - that’s tightly bound to the service, but there’s nowhere to put it at the moment. + +It's also worth noting that the GAMMA discussion has made clear the distinction between the Kubernetes Service as a frontend (an identity and place to attach routing information to), and as a backend (as a grouping of endpoints). This GEP is concerned with backend capabilities, so it's concerned with the latter. + +This initial form of this GEP is for the Gateway API community to agree on what problem we’re solving and why. + +### Why build something? + +We've got the following feature requests and discussions in the Gateway API repo: +- [#1244](https://github.com/kubernetes-sigs/gateway-api/discussions/1244) : Unclear how to specify upstream (webserver) HTTP protocol. This issue describes the problems that Evan had in trying to be able to define if a backend behind a HTTPRoute supports HTTP2 over cleartext or websockets. The question of how to tell the Gateway implementation that the backend needs TLS details for a proxy-based implementation to be able to connect it also came up in the discussion. +- [#1285](https://github.com/kubernetes-sigs/gateway-api/discussions/1285) has a more specific discussion about how different ingress implementations allow this to be configured today, whether that's with the Ingress resource or their own custom one. The great roundup that Candace did is reproduced in the next few bullet points. + * Istio uses a [DestinationRule resource with ClientTLSSettings](https://istio.io/latest/docs/reference/config/networking/destination-rule/#ClientTLSSettings) to capture TLS details, and the DestinationRule resource also holds traffic policy information like load balancing algorithm, connection pool size, and so on. + * OpenShift’s Route resource allows the [configuration of reencryption](https://docs.openshift.com/container-platform/4.10/networking/routes/secured-routes.html#nw-ingress-creating-a-reencrypt-route-with-a-custom-certificate_secured-routes) specifically, along with custom certificate details. + * Contour’s HTTPProxy captures TLS details using an Envoy client certificate, destination CA certificate, and optional SubjectName which sets what Envoy should expect to see from the backend service, all inside the HTTPProxy resource. It also requires either a Protocol field inside the HTTPProxy, or an annotation on the Service that tells Contour that the service expects TLS. This is [all documented](https://projectcontour.io/docs/v1.21.1/config/upstream-tls/), but I should note that Contour’s docs use the Envoy convention where a backend in Gateway parlance is called an Upstream (which may be confusing if you’re not used to it). + * Linkerd uses a [Server resource](https://linkerd.io/2.11/reference/authorization-policy/#server) (which is functionally pretty similar to Service in that it associates a name with a Pod selector, but also has other details like if the service supports Proxy protocol), along with a ServerAuthorization resource that specifies some constructs that sit more at the service mesh level, including identity and access control. + +In terms of other implementations existing use cases for features like this: +- For Contour, there are annotations to allow the configuration of the following on a backend Service: + - Max connections + - Max pending requests + - Max requests + - Max retries + - Upstream protocol: This is what allows Contour to handle switching protocols for the backend service. +- In Istio, the `DestinationRule` resource allows the configuration of many settings like this: + - Load balancer algorithms + - Connection pool settings + - Outlier Detection + - Tunnel settings for non-HTTP workloads +- In Consul, [`ServiceDefaults`](https://www.consul.io/docs/connect/config-entries/service-defaults) allows specifying similar configuration: + - Max connections + - Max pending requests + - Max concurrent requests + - Protocol + - Passive health check interval and max failures (outlier detection) + - TLS SNI (we don't support configuring a specific CA at this granularity, but publishing a public key in a status field could be useful) + +The properties we're talking about all share two things: +- They are tightly bound to the backend, rather than being important at the route level +- And the service owner (application developer in the Gateway API personas) should control these settings, not the owner of the Gateway implementation (the Cluster Operator) + +A good example is the load balancing algorithms for backends, as distinct from load balancing for routes. Load balancing for routes is about choosing which route option the implementation should choose, while load balancing for backends is about which endpoint from the backend the implementation should send traffic to if that backend's route is chosen. To put this in GAMMA initiative terms, load balancing for Routes is a frontend concern that's addressed with config in the HTTPRoute (or other Route resource), while load balancing for backends is a backend concern. + +It's likely that these will need to be set differently (for example, random load balancing at the route level for canarying between services, with Weighted Least Request at the backend level for the actual endpoints). This was discussed quite extensively in the [PR for GEP-992](https://github.com/kubernetes-sigs/gateway-api/pull/993), which ended up not going ahead. See [GEP-992](https://github.com/kubernetes-sigs/gateway-api/issues/992) for more details. + +The existing resources we have (Service and HTTPRoute) don’t have space for this information currently, so we need to do *something*. + +### What we're building + +We’re looking to add specific, structured extension points somewhere in the resources used by the Gateway API to describe properties and capabilities of backend services. + +Those specific, structured extension points need to be in a place where they can be owned by the person who owns the backend, since that could be different to the person who owns the Route. That is, whatever we choose should be something that extends a thing that is referred to by a `backendRef` in a Route, not inside the Route. + +The initial list includes, but is not limited to: +* TLS information for connection from the Gateway to the backend service. Note that this doesn’t include any information used for service mesh encryption, just what a Gateway’s proxy would need to be able to connect to the backend service. +* Websocket protocol information for the backend service. +* Protocol disambiguation for “upgradeable” protocols like HTTP/2 and HTTP/1.1 which operate on the same port. (Websockets may be another case of this.) + +Of course, from the section above, you can see that there are many other features and capabilities that can sit in at this level, which is why we want to ensure that this is a more general design. + +## API + +To be written later, once we have agreement on the “what” and the “why”. (This is the “how”). + + +## Alternatives + +Again, we need to wait until we’re writing the “how”. + +## References + +(Add any additional document links. Again, we should try to avoid +too much content not in version control to avoid broken links) diff --git a/site-src/ko/geps/gep-1282/metadata.yaml b/site-src/ko/geps/gep-1282/metadata.yaml new file mode 100644 index 0000000000..481acc5fbf --- /dev/null +++ b/site-src/ko/geps/gep-1282/metadata.yaml @@ -0,0 +1,15 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1282 +name: Describing Backend Properties +status: Declined +authors: + - youngnick +relationships: + obsoletedBy: + - number: 1897 + name: BackendTLSPolicy - Explicit Backend TLS Connection Configuration + description: Implements just part of the Backend Properties GEP. + - number: 1911 + name: Backend Protocol Selection + description: Protocol selection was one of the Backend Properties. diff --git a/site-src/ko/geps/gep-1294/index.md b/site-src/ko/geps/gep-1294/index.md new file mode 100644 index 0000000000..5fb1c0a3ed --- /dev/null +++ b/site-src/ko/geps/gep-1294/index.md @@ -0,0 +1,476 @@ +# GEP-1294: xRoutes Mesh Binding + +* Issue: [#1294](https://github.com/kubernetes-sigs/gateway-api/issues/1294) +* Status: Standard + +## Overview + +Similar to how `xRoutes` bind to `Gateways` and manage North/South traffic flows in Gateway API’s ingress use-case, it would be natural to adopt a similar model for traffic routing concerns in service mesh deployments. The purpose of this GEP is to add a mechanism to the Gateway API spec for the purpose of associating the various `xRoute` types to a service mesh and offering a model for service owners to manage traffic splitting configurations. + +This GEP is intended to establish an implementable, but experimental, baseline for supporting basic service mesh traffic routing functionality through the Gateway API spec. + +## Personas + +This GEP uses the [roles and personas](../../concepts/security-model.md#roles-and-personas) defined in the Gateway API security model, and the service "producer" and "consumer" roles defined in [GEP-1324: Service Mesh in Gateway API](../gep-1324/index.md#producer-and-consumer). + +## Goals + +* MUST allow `xRoute` traffic rules to be configurable for a mesh service by the application owner/producer. +* SHOULD allow control by the cluster operator (mesh administrator) to grant permission for whether `xRoute` resources in a given namespace are allowed to configure mesh traffic routing. +* SHOULD NOT require downstream "consumer" services to update configuration or DNS addresses for traffic to follow "producer" mesh routing rules configured by upstream services. +* SHOULD NOT require reconfiguring existing `xRoute` resources for North/South Gateway configuration. + +## Non-Goals + +* Supporting "egress" use cases, which is currently a deferred goal, including: + * Defining how "consumer" traffic rules which could override routing for service upstreams only within the local scope of a namespace or service might be configured. + * Redirecting calls from arbitrary custom domains to an in-cluster service. +* Defining how multiple `Services` or `EndpointSlices` representing instances of a single "logical" service should present an identity for AuthN/AuthZ or be associated with each other beyond routing rules. +* Defining how AuthZ should be implemented to secure East/West traffic between services. +* Defining how [Policy Attachment](../../reference/policy-attachment.md) would bind to `xRoute`, services or a mesh. +* Defining how `Routes` configured for East/West service mesh traffic management might integrate with North/South `Gateways`. + * This is a bit tricky in that it's effectively a form of delegation as described in [GEP-1058: Route Inclusion and Delegation](https://github.com/kubernetes-sigs/gateway-api/pull/1085), and is planned to be explored in a future GEP. +* Handling East/West traffic outside the cluster (VMs, etc). + +## Implementation Details and Constraints + +* MUST set a status field on `xRoute` to show if the routing configuration has been applied to the mesh. +* MUST only be allowed to configure "producer" traffic rules for a `Service` in the same namespace as the `xRoute`. + * Traffic routing configuration defined in this way SHOULD be respected by ALL consumer services in all namespaces in the mesh. +* MAY assume that a mesh implements "transparent proxy" functionality to redirect calls to the Kubernetes DNS address for a `Service` through mesh routing rules. + +## Introduction + +It is proposed that an application owner should configure traffic rules for a mesh service by configuring an `xRoute` with a Kubernetes `Service` resource as a `parentRef`. + +This approach is dependent on both the "frontend" role of the Kubernetes `Service` resource as defined in [GEP-1324: Service Mesh in Gateway API](../gep-1324/index.md#service) when used as a `parentRef` and the "backend" role of `Service` when used as a `backendRef`. The conformant implementation would use the Kubernetes `Service` name to match traffic for meshes, but the `backendRef` endpoints would ultimately be used for the canonical IP address(es) to which traffic should be redirected by rules defined in this `xRoute`. This approach leverages the existing points of extensibility within the Gateway API spec, and would not require introducing any API changes or new resources, only defining expected behavior. + +### Why Service? + +The GAMMA initiative has been working to bring service mesh use-cases to the Gateway API spec, taking the best practices and learnings from mesh implementations and codifying them in a spec. Most mesh users are familiar with using the Kubernetes Service resource as the foundation for traffic routing: not only do service meshes take advantage of the IP address management and corresponding DNS functionality provided by Service, but one of the key value propositions of service meshes is that they can be added "on top" of preexisting deployments, which are almost certain to already be using Service resources. This architecture is generally a simple, effective way for service meshes to operate. + +Add to that the ubiquity of Service in the Kubernetes ecosystem as well as the time and effort needed to get support for a new resource into the ecosystem (especially true for managed Kubernetes providers), and it's clearly impractical to force GAMMA to wait for a replacement for Service. + +Unfortunately, Service is a badly overloaded resource. It orchestrates not only IP address allocation and DNS but also endpoint collection and propagation, load balancing, etc. For this reason, it cannot be the only long-term answer for `parentRef` binding -- however, it is the only feasible option that mesh implementations have today, and as such the graduated GAMMA specification MUST support Service as a `parentRef`. + +We expect this situation to change -- and, indeed, we plan to be a part of that change. Luckily, `parentRef` is flexible enough to support additional resources in the future, which allows work on adding a Service alternative in GAMMA to begin and continue in parallel with the graduation of this spec. In fact, we believe that GAMMA's use case can serve as an excellent basis for developing and trialing new, more composable mechanisms for managing IP address allocation and DNS. + + +## API + +```yaml +metadata: + name: foo-route + namespace: store +spec: + parentRefs: + - kind: Service + name: foo + rules: + backendRefs: + - kind: Service + name: foo + weight: 90 + - kind: Service + name: foo-v2 + weight: 10 +``` + +In the example above, routing rules have been configured to direct 90% of traffic for the `foo` `Service` to the default "backend" endpoints specified by the `foo` `Service` [`selector`](https://kubernetes.io/docs/concepts/services-networking/service/#defining-a-service) field, and 10% to the `foo-v2` `Service`. This is determined based on the `ClusterIP` (for `Service`) and `ClusterSetIP` (for `ServiceImport`) matching, and for "transparent proxy" mesh implementations would match all requests to `foo.svc.cluster.local` (or arbitrary custom suffix, as the hostname is not specified manually) from within the same namespace, all requests to `foo.store.svc.cluster.local` from other namespaces, and all requests to `foo.store.svc.clusterset.local` for multicluster services, within the scope of the service mesh. + +### Route presence + +When no `xRoute` resources are defined, all traffic should implicitly work - this is just how Kubernetes functions. When you create an `xRoute` targeting a service as a `parentRef` you are replacing that implicit logic - not adding to it. Therefore, you may be reshaping or restricting traffic via an `xRoute` configuration (which should be noted, is distinct from *disallowing* traffic by AuthZ). + +### Allowed service types + +Services valid to be selected as a `parentRef` SHOULD have a way to identify traffic to them - typically by one or more virtual IP(s), DNS hostname(s), or name(s). + +Implementations SHOULD support the default [`ClusterIP`](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) `Service` type as a `parentRef`, with or without selectors. + +["Headless" `Services`](https://kubernetes.io/docs/concepts/services-networking/service/#headless-services) SHOULD NOT be supported as a `parentRef`, because they do not implement the "frontend" functionality of a service. + +`Service` resource with [`type: NodePort`](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) or [`type: LoadBalancer`](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) MAY be allowed as `parentRefs` or `backendRefs`, as these do provision virtual IPs and are effectively `ClusterIP` services with additional functionality, but it should typically be preferred to expose services publicly through the North/South Gateway API interfaces instead. + +`Service` resources with [`type: ExternalName`](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) SHOULD NOT be allowed as `parentRefs` or `backendRefs` due to [security concerns](https://github.com/kubernetes/kubernetes/issues/103675), although might eventually play some role in [configuring egress functionality](https://github.com/kubernetes-sigs/gateway-api/issues/1070). + +Services supported as `backendRefs` SHOULD be consistent with expectations for North/South Gateway API implementations, and MUST have associated endpoints. `ClusterIP` `Services` with selectors SHOULD be supported as a `backendRef`. + +#### `Service` without selectors + +An alternate pattern additionally supported by this approach would be to target a `Service` without selectors as the `parentRef`. This could be a clean way to create a pure routing construct and abstract a logical frontend, as traffic would resolve to a `backendRef` `Service` with selectors defined on the `HTTPRoute`, or receive a 4xx/5xx error response if no matching path or valid backend was found. + +### `parentRef` Conformance Levels + +Currently (v0.7.0), this spec only considers the `Service` resource to be under Core conformance as a `parentRef`. However, Service is not the only resource that can fulfill the frontend role. While the Gateway API spec couldn’t possibly enumerate every existing (and future) frontend-like resource, it can specify a subset of resources that implementations MUST support as parentRefs under as a part of core conformance. Meshes MAY support other implementation-specific resources as parentRefs. The spec maintainers also reserve the right to add additional resources to core conformance as the spec evolves. + +#### Extended Conformance + +In addition to Service, there are other optional parentRef resources that, if used by implementations, MUST adhere to the spec’s prescriptions. At the time of writing (v0.7.0), there is one resource in extended conformance: `ServiceImport` (part of the [MCS API](https://github.com/kubernetes-sigs/mcs-api), currently in alpha). The semantics of `ServiceImport` `parentRef` binding can be found in [GEP-1748](../gep-1748/index.md) (Note: Headless `ServiceImport` is out of scope and not currently a part of the spec). + +##### Why not `IPAddress` + +In Kubernetes 1.27, there will be a new IPAddress resource added to networking.k8s.io/v1alpha1 as part of [KEP 1880](https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/1880-multiple-service-cidrs#proposal). Naturally, it makes sense to examine whether or not this new resource makes sense as a GAMMA aware parentRef. At first glance, IPAddress seems to be an appropriate abstraction for the “frontend” role we’ve been discussing; every Kubernetes Service is accessed over the network via one of its ip addresses. Furthermore, the fact that the Service resource auto-creates an IPAddress is encouraging. However, the fact that the name of the IPAddress is simply the decimal/hex ip address and not a human-readable Service name makes the UX untenable as a spec-supported parentRef. However, `IPAddress` is NOT disallowed; implementations may use it if they wish. + +#### Implementation-specific `parentRef`s + +If mesh implementations wish to enable an implementation-specific resource as a parentRef, they may do so as long as that resource meets certain conditions. Recall that the frontend role of a (generic) service is how one calls the service. In the service mesh transparent proxy context, the frontend role (and parentRef by extension) is effectively the matching mechanism for the specified route. For the Service parentRef, this means that the mesh should apply a particular xRoute’s configuration if the destination ip address for a given connection is the ClusterIP of that parentRef Service. If a mesh wishes to use an implementation-specific resource for parentRef, that resource MUST contain layer-appropriate information suitable for traffic matching (e.g. no Host header capture in TCPRoute). For example, the following HTTPRoute with an Istio `ServiceEntry` as a parentRef would be a valid implementation-specific reference: + +```yaml +apiVersion: networking.istio.io/v1beta1 +kind: ServiceEntry +metadata: + name: internal-svc-httpbin + namespace : egress +spec: + hosts: + - example.com + exportTo: + - "." + location: MESH_INTERNAL + ports: + - number: 80 + name: http + protocol: HTTP + resolution: DNS +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: mongo-internal +spec: + parentRefs: + - kind: ServiceEntry + group: networking.istio.io/v1beta1 + name: internal-svc-httpbin + namespace: egress + sectionName: http # referencing the port name + rules: + - backendRefs: + - name: internal-example + port: 80 +``` + +##### `Gateways` + +There has been much discussion around cluster local Gateways (i.e. Gateways not associated with a traditional load balancer). While there are various potential UX impairments (e.g. what’s the difference between a GAMMA HTTPRoute with a Gateway parentRef and an ingress implementation’s HTTPRoute?), there is no technical reason why a Gateway cannot be a valid GAMMA parentRef if an implementation wishes to do so. + +### Route types + +All types currently defined in the gateway-api core (`HTTP`, `GRPC`, `TCP`, `TLS`, and `UDP`) are available for use in a Mesh implementation. + +If multiple routes with different types both bind to the same Service and Port pair, only a single route type should be applied. The rejected routes should be ignored and have the `RouteConditionAccepted` status set to the (new) reason `RouteReasonConflicted`. + +Route type specificity is defined in the following order (first one wins): + +1. GRPCRoute +2. HTTPRoute +3. TLSRoute +4. TCPRoute + +Because UDP is its own protocol, it is orthogonal to these precedence order. Since there is only one UDP-based route, there is currently no conflicts possible; if other UDP-based routes are added a similar ordering will be defined. + +Note: these conflicts only occur when multiple *different* route types apply to the same Service+Port pair. Multiple routes of the same type are valid, and merge according to the route-specific merging semantics. + +### Ports + +By default, a `Service` attachment applies to all ports in the service. Users may want to attach routes to only a *specific* port in a Service. To do so, the `parentRef.port` field should be used. + +If `port` is set, the implementation MUST associate the route only with that port. +If `port` is not set, the implementation MUST associate the route with all ports defined in the Service. + +### `hostnames` field + +GAMMA implementations SHOULD NOT infer any functionality from the `hostnames` field on `xRoute`s (currently, `TLSRoute`, `HTTPRoute`, and `GRPCRoute` have this field) due to current under-specification and reserved potential for future usage or API changes. + +For the use case of filtering incoming traffic from selected HTTP hostnames, it is recommended to guide users toward configuring [`HTTPHeaderMatch`](../../reference/spec.md#gateway.networking.k8s.io%2fv1beta1.HTTPHeaderMatch) rules for the [`Host`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host) header. Functionality to be explored in future GEPs may include supporting concurrent usage of an `xRoute` traffic configuration for multiple North/South `Gateways` and East/West mesh use cases or redirection of egress traffic to an in-cluster `Service`. + +### Namespace boundaries + +In a mesh, routes can be configured by two personas: + +* Service producers, who want to modify behavior of *inbound* requests to their services +* Service consumers, who want to modify behavior of *outbound* requests to other services. + +While these concepts are not directly exposed in the API, a route is implicitly fulfilling one of these roles and behaves differently depending on the role. + +A route is a producer route when the `parentRef` refers to a service in the *same namespace*. This route SHOULD apply to all incoming requests to the service, including from clients in other namespaces. + +Note: Some implementations may only be able to apply routes on client-side proxies. As a result, these will likely only apply to requests from clients who are also in the mesh. + +A route is a consumer route when the `parentRef` refers to a service in *another namespace*. Unlike producer routes, consumer routes are scoped only the same namespace. This ensures that for traffic between two namespaces, another unrelated namespace cannot modify their traffic. + +Routes of either type can send traffic to `backendRefs` in any namespace. Unlike `Gateway` bound routes, this is allowed without a `ReferenceGrant`. In `Gateway`-bound routes (North-South), routes are opt-in; by default, no Services are exposed (often to the public internet), and a service producer must explicitly opt-in by creating a route themselves, or allowing another namespace to via `ReferenceGrant`. For mesh, routes *augment* existing Services, rather than exposing them to a broader scope. As a result, a `ReferenceGrant` is not required in most mesh implementations. Access control, if desired, is handled by other mechanism such as `NetworkPolicy`. While uncommon, if a mesh implementation *does* expose the ability to access a broader scope than would otherwise be reachable, then `ReferenceGrant` must be used for cross namespaces references. + +### Multiple routes for a Service + +A service may be used as a `parentRef` (where we attach to the "Service Frontend") or as a `backendRef` (where we attach to the "Service Backend"). + +In general, when a request is sent to a Service frontend (ex: `curl svc`), it should utilize a Route bound to that Service. +However, when sent to a Service backend (ex: `curl pod-ip`), it would not. + +Similarly, if we have multiple "levels" of Routes defined, only the first will be used, as that is the only one that accesses the Service frontend. + +Consider a cluster with routes for a Service in both a Gateway, consumer namespace, and producer namespace: + +* Requests from the Gateway will utilize the (possibly merged) set of routes attached to the Gateway +* Requests from a namespace with consumer routes will utilize the (possibly merged) set of routes in the consumer namespace +* Requests from other namespaces will utilize the (possibly merged) set of routes in the producer namespace + +The merging of routes occurs only within groups of the same type of routes (Gateway bound, producer, or consumer), and follows the standard route merging behavior already defined. + +Note: a possible future extension is to allow `backendRefs` to explicitly target a "frontend" or "backend". This could allow chaining multiple routes together. However, this is out of scope for the current GEP. + +### Drawbacks + +* The fact that this pattern is used for mesh configuration is implicit - this may benefit from some additional configuration to map the `HTTPRoute` to a particular mesh implementation rather than being picked up by any or all GAMMA meshes present in a cluster. Possible approaches include: +* [GEP-1282: Describing Backend Properties](../gep-1282/index.md) may be one path to associating a `Service` with a mesh, but likely wouldn't be able to handle the application of multiple `HTTPRoutes` for the same `Service`, but each intended for different mesh implementations + * It's currently unclear how relevant this constraint may be, but associating an `HTTPRoute` with a mesh by this method would additionally require an extra graph traversal step. +* Expecting a `Mesh` `parentRef` or similar reference as proposed in [GEP-1291: Mesh Representation](https://docs.google.com/document/d/1oyA9uUH7pNNxxwy3WZGSWx-edHDBLrujcezr8q3el70/edit#) may be a preferred eventual path forward, but wouldn't be required initially, with the assumption that only one mesh should typically be present in a cluster. +* No mechanism for egress redirection of traffic from arbitrary hostnames to a mesh service within this approach (but could still be implemented separately). + +## Alternatives + +### New `MeshService` (or `HttpService`, `VirtualService`, `ServiceBinding`) resource as `parentRef` + +Introduce a new resource to represent the "frontend" role of a service as defined in [GEP-1291: Mesh Representation](https://docs.google.com/document/d/1oyA9uUH7pNNxxwy3WZGSWx-edHDBLrujcezr8q3el70/edit#). + +#### Controller manages new DNS hostname + +A controller could create a matching selector-less `Service` (i.e. no endpoints), to create a `.cluster.local` name, or could interact with [external-dns](https://github.com/kubernetes-sigs/external-dns) to create a DNS name in an owned domain. + +Ownership/trust would remain based on naming pattern: `serviceName.namespace.svc.[USER_DOMAIN]` + +Separate `HttpService`, `TlsService` and `TcpService` resources could have the benefit of allowing us to define protocol specific elements to the spec along with an embedded `CommonServiceSpec`, similar to [`CommonRouteSpec`](../../reference/spec.md#gateway.networking.k8s.io/v1.CommonRouteSpec), and keep similar patterns as `Service`. + +##### Drawbacks + +* May require reconfiguring existing applications to point to a new mesh service hostname - adoption wouldn't be "transparent". +* The pattern of creating a new pure routing construct would still be implementable following the proposed approach, by manually creating and targeting a new `Service` without selectors as a `parentRef`, without the overhead of introducing a new resource. + +#### Manage DNS by binding to an existing `Service` + +A new `ServiceBinding` resource would directly reference an existing `Service` to determine which traffic should be intercepted and redirected following configured service mesh routing rules and facilitate "transparent proxy" functionality. This resource could possibly share similar responsibilities as the need identified in [GEP-1282: Describing Backend Properties](../gep-1282/index.md). + +``` +kind: ServiceBinding +metadata: + name: foo_binding +spec: + parentRefs: + - kind: Service + name: foo +--- +spec: + parentRefs: + - kind: ServiceBinding + name: foo_binding + rules: + backendRefs: + - kind: Service + name: foo + weight: 90 + - kind: Service + name: foo_v2 + weight: 10 +``` + +While the `HTTPRoute` does not directly reference a particular mesh implementation in this approach, it would be possible to design the `ServiceBinding` resource to specify that. + +##### Drawbacks + +* Introduces an extra layer of abstraction while still having several of the same fundamental drawbacks as a direct `parentRef` binding to `Service`. +* May require reconfiguring `Gateway` `HTTPRoutes` to specify `ServiceBindings` as `backendRefs`. + +#### Drawbacks + +* The split frontend/backend role of `Service` is fundamentally an issue with the `Service` resource, and while upstream changes may be quite slow, this would likely be best addressed through an upstream KEP - introducing a new resource to GAMMA now would likely result in API churn if we expect a similar proposal to be upstreamed eventually. +* Adopting the proposed `Service` as `parentRef` approach wouldn't foreclose the possibility of migrating to a new frontend-only resource in the future, and wouldn't even require a breaking change to `HTTPRoute`, just adding support for a new `parentRef` `Kind`. +* Would be less clear how to integrate with transparent proxy functionality - it may be possible to design some way to select a `Service` or hostname to intercept, but abstraction through a separate resource would make configuration more complex. + +### `Mesh` resource as `parentRef` + +This binds an `HTTPRoute` directly to a cluster-scoped `Mesh` object as defined in [GEP-1291: Mesh Representation](https://docs.google.com/document/d/1oyA9uUH7pNNxxwy3WZGSWx-edHDBLrujcezr8q3el70/edit#). + +``` +spec: + parentRefs: + - kind: Mesh + name: cool-mesh +``` + +It is currently undefined how this approach may interact with either explicitly configured [`hostnames`](../../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteSpec) or implicit "transparent proxy" routing for Kubernetes `Services` to determine how traffic should be intercepted and redirected. + +This approach is not entirely abandoned, as it could supplement the proposed approach if explicit attachment to a specific mesh is deemed necessary. Additionally, this approach may offer a future option for attaching an `HTTPRoute` to a mesh, but not a specific service (e.g. to implement mesh-wide egress functionality for all requests to a specific hostname). + +#### Peer to `Service` resource `parentRef` + +An `HTTPRoute` could specify a `Mesh` resource `parentRef` as a peer to a `Service` resource `parentRef`. + +``` +spec: + parentRefs: + - kind: Mesh + name: cool-mesh + - kind: Service + name: foo +``` + +##### Drawbacks + +* Would require separate `HTTPRoute` resources to explicitly define _different_ traffic routing rules for the same service on different meshes. + +#### Nested `services` and `hostnames` fields in [`ParentReference`](../../reference/spec.md#gateway.networking.k8s.io/v1.ParentReference) + +In core conformance, the `services` would only be valid for `Mesh` types, and `hostnames` field only for `Gateway`. Mesh implementations could still use a `Host` header match if they wanted limit rules to specific hostnames. + +``` +parentRefs: +- kind: Mesh + name: coolmesh + services: + - name: foo + kind: Service +- kind: Gateway + name: staging + hostnames: [staging.example.com] +- kind: Gateway + name: prod + hostnames: [prod.example.com] +# Top level hostnames field removed +``` + +Moving the `hostnames` field from `HTTPRoute` to `ParentReference` might introduce a clean path for concurrently using a route across North/South and mesh use cases, even without introducing the `services` field or a new `Mesh` resource, and even makes pure North/South implementations more flexible by allowing a hostname-per-`Gateway` scope. + +##### Drawbacks + +* Substantial API change, impacting even North/South use cases +* Extending this functionality to support mesh-wide egress or arbitrary redirection may still require some sort of bidirectional handshake with a `Hostname` resource to support configuration across namespaces and limit conflicting configuration. + + +#### Phantom `parentRef` +``` +spec: + parentRefs: + - kind: Mesh + name: istio +``` + +This is done by configuring the `parentRef`, to point to the `istio` `Mesh`. This resource does not actually exist in the cluster and is only used to signal that the Istio mesh should be used. In Istio's [experimental implementation](https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/#mesh-traffic), the `hostnames` field on `HTTPRoute` is used to match mesh service traffic to the routing rules. + +### New field on `HTTPRoute` for `Service` binding + +A new field `serviceBinding` would be added to `HTTPRoute` to attach to the `Service`. Alternatively, this could be a new field in [`HTTPRouteMatch`](../../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteMatch). As with the proposed implementation, this approach could be combined with a `Mesh` resource or similar as the `parentRef`, which would just define that the route would be applied to a mesh. + +``` +spec: + serviceBinding: + name: my-service +``` + +OR + +``` +spec: + matches: + service: + name: my-service +``` + +For either implementation, the type of the `serviceBinding` or `service` field should likely be a struct with `Group` (defaulting to the Kubernetes core API group when unspecified), `Kind` (defaulting to `Service` when unspecified) and `Name` fields, to allow for extensibility to `ServiceImport` or custom mesh service types. + +#### Drawbacks + +* API addition required, which is somewhat awkwardly ignored for North/South use cases, and could complicate potential for concurrent use of an `HTTPRoute` across both North/South and mesh use cases. +* Adding new fields to a relatively stable resource like `HTTPRoute` could be difficult to do in an experimental way. +* Following this pattern may lead to subsequent additional fields to further clarify or extend behavior. + +### `Gateway` resource with `class: mesh` as `parentRef` + +To support arbitrary DNS names (owned by a "domain owner persona") we would need a similar mechanism to what `Gateway` is using for delegating management of `HTTPRoutes` to namespaces. Instead of duplicating everything - we could use `Gateway` as is, with `class: mesh` (or matching the mesh implementation desired name). + +``` +kind: Gateway +spec: + class: mesh + listeners: + - name: example + hostname: "example.com" +--- +kind: HTTPRoute +spec: + parentRefs: + name: foo_gateway + sectionName: example + hostnames: ["example.com", "foo.svc.cluster.local"] +``` + +Functionally such a mesh could be implemented using the existing gateway spec - a GAMMA implementation would only remove the extra hop through the `Gateway`, using sidecars, or it may use a specialized per-namespace gateway to isolate the mesh traffic (like [Istio Ambient](https://istio.io/latest/blog/2022/introducing-ambient-mesh/)). Proxyless gRPC could also use this to route directly. + +This solution could work well for both non-`cluster.local` names but also for egress, where a `Gateway` with `class: egress` could define names that are external to the mesh and need to either have policies applied or go to a dedicated egress gateway. + +#### Drawbacks + +* Using the `HTTPRoute` `hostnames` field to match mesh traffic breaks from the typical Gateway API pattern of explicit Kubernetes resource references, is extremely implicit, and could reduce portability of configuration. +* Potentially unclear translation between conceptual resource and concrete implementation, particularly for "proxyless" mesh implementations. +* Service meshes may wish to express [egress](https://istio.io/latest/docs/tasks/traffic-management/egress/egress-gateway/) or [other "in-mesh" gateways](https://www.consul.io/docs/connect/gateways) through an API like this, and it could be confusing to overload this resource too much or conflate different personas who may wish to manage mesh service traffic routing as an application owner separately from egress rules as a service consumer or cluster operator. + +### `ServiceProjection` resource as `parentRef` and `backendRefs` + +This approach is similar to the above `ServiceBinding` proposal with a couple of major differences: + +* `ServiceProjection` encapsulates both "frontend" and "backend" roles of the `Service` resource +* `ServiceProjection` could handle the full responsibilities described in [GEP-1282: Describing Backend Properties](../gep-1282/index.md) + +``` +kind: ServiceProjection +metadata: + name: foo + namespace: store +spec: + serviceRef: + name: foo + kind: Service|ServiceImport + roles: + frontend: + backend: + loadbalancerConfig: + strategy: RoundRobin + clientTLS: + secretRef: + ... +--- +kind: HTTPRoute +metadata: + name: foo_route + namespace: store +spec: + parentRefs: + - kind: ServiceProjection + name: foo + role: frontend + rules: + backendRefs: + - kind: ServiceProjection + name: foo + role: backend + weight: 90 + - kind: ServiceProjection + role: backend + name: foo_v2 + weight: 10 +``` + +For convenience, `ServiceProjection` could have a `meshRef` field that, when set instead of `serviceRef`, makes all configuration within the `ServiceProjection` apply to all services in the mesh (the mesh control plane would need to read the `Mesh` resource). Pursuant to the changes to status semantics in [GEP-1364: Status and Conditions Update](../gep-1364/index.md), it is necessary for the route to attach to something; in this case, the route attaches to the specific role or profile of the `ServiceProjection` and the mesh control plane should update the route status to reflect that. + +#### Drawbacks + +* May require reconfiguring `Gateway` `HTTPRoutes` to specify `ServiceProjections` as `backendRefs`. +* Verbose boilerplate for each service. + +### Implicit backendRef + +An initial iteration of this GEP had the ability to omit a `backendRef` and have it implicitly be set the same as the `parentRef`. +This has been removed due to inconsistency with Gateway `parentRefs` and tight coupling of the "frontend" and "backend" roles. + +Implementations MUST respect the standard `backendRef` rules as defined by the existing spec. diff --git a/site-src/ko/geps/gep-1294/metadata.yaml b/site-src/ko/geps/gep-1294/metadata.yaml new file mode 100644 index 0000000000..8e06133a0d --- /dev/null +++ b/site-src/ko/geps/gep-1294/metadata.yaml @@ -0,0 +1,16 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1294 +name: xRoutes Mesh Binding +status: Standard +authors: + - mikemorris + - howardjohn + - keithmattix +relationships: + extends: + - number: 1324 + name: Service Mesh in Gateway API + description: Adds initial Service binding proposal +changelog: + - "https://github.com/kubernetes-sigs/gateway-api/pull/2688" diff --git a/site-src/ko/geps/gep-1323/index.md b/site-src/ko/geps/gep-1323/index.md new file mode 100644 index 0000000000..09459f3fa3 --- /dev/null +++ b/site-src/ko/geps/gep-1323/index.md @@ -0,0 +1,215 @@ +# GEP 1323: Response Header Filter + +* Issue: [#1323](https://github.com/kubernetes-sigs/gateway-api/issues/1323) +* Status: Standard + +> **Note**: This GEP is exempt from the [Probationary Period][expprob] rules of +> our GEP overview as it existed before those rules did, and so it has been +> explicitly grandfathered in. + +[expprob]:../overview.md#probationary-period + +## TLDR +Similar to how we have `RequestHeaderModifier` in `HTTPRouteFilter`, which lets users modify request headers before the request is forwarded to a backend (or a group of backends), it’d be helpful to have a `ResponseHeaderModifier` field which would let users modify response headers before they are returned to the client. + +## Goals +* Provide a way to modify HTTP response headers in a `HTTPRoute`. +* Reuse existing types as much as possible to reduce boilerplate code. + +## Non Goals +* Provide a way to modify other parts of a HTTP response like status code. +* Add fields specifically for standard headers such as `Cookie`. + +## Introduction +Currently, the `HTTPRouteFilter` API provides a way for request headers to be modified through the `RequestHeaderModifier` field of type `HTTPRequestHeaderModifier`. But, a similar API to modify response headers does not exist. This proposal intends to introduce a new field in `HTTPRouteFilter` named `ResponseHeaderModifier`. + +## API +We could introduce a new API named `HTTPResponseHeaderModifier` which would look exactly like the existing `HTTPRequestHeaderModifier` API. But since HTTP headers have the same semantics for both requests and responses, it makes more sense to rename `HTTPRequestHeaderModifier` to `HTTPHeaderModifier` and use this for both `RequestHeaderModifier` and `ResponseHeaderModifier`. + +```golang +// HTTPHeaderModifier defines a filter that modifies the headers of a HTTP +// request or response. +type HTTPHeaderModifier struct { + // Set overwrites the request with the given header (name, value) + // before the action. + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=16 + Set []HTTPHeader `json:"set,omitempty"` + + // Add adds the given header(s) (name, value) to the request + // before the action. It appends to any existing values associated + // with the header name. + + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=16 + Add []HTTPHeader `json:"add,omitempty"` + + // Remove the given header(s) from the HTTP request before the action. The + // value of Remove is a list of HTTP header names. Note that the header + // names are case-insensitive (see + // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + // +optional + // +kubebuilder:validation:MaxItems=16 + Remove []string `json:"remove,omitempty"` +} +``` + +Given the fact that this functionality is offered by only a few projects that currently implement Gateway API when using their own traffic routing CRDs, it’s better to support `ResponseHeaderModifier` as an _Extended_ feature, unlike `RequestHeaderModifier` which is a _Core_ feature. This will also not increase the difficulty of implementing Gateway API for any future ingress or service mesh. + +This feature can be further extended via [Policy Attachment](../../reference/policy-attachment.md). The mechanism and use cases of this may be explored in a future GEP. + +## Usage +Adding support for this unlocks a lot of real world use cases. Let’s review a couple of them: + +* A team has a frontend web app, along with two different versions of their backends exposed as Kubernetes services. If, the frontend needs to know which backend it’s talking to, this can be easily achieved without any modifications to the application code. + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: http-response-header +spec: + hostnames: + - response.header.example + rules: + - backendRefs: + - name: example-svc-beta + weight: 50 + port: 80 + # set a custom header for all responses being sent from the beta build of the backend server. + filters: + - type: ResponseHeaderModifier + responseHeaderModifier: + add: + name: build + value: beta + - name: example-svc-stable + weight: 50 + port: 80 +``` + +* Cookies can be automatically injected into the response of services. This can enable services to identify users that were redirected to a certain backend. + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: http-response-header +spec: + hostnames: + - response.header.example + rules: + # match against any requests that has the cookie set due to the below rule + - matches: + - headers: + type: Exact + name: Cookie + value: user=insider + backendRefs: + - name: foo-svc + port: 8080 + + - filters: + - type: ResponseHeaderModifier + # set cookies for all requests being forwarded to this service + responseHeaderModifier: + set: + name: Set-Cookie + value: user=insider + backendRefs: + - name: example-svc + weight: 1 + port: 80 +``` + +> Note: Some projects like Envoy support interpolating a few predefined [variables into header values](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#custom-request-response-headers). Similar functionality might be supported by other implementations but its unlikely to be portable and thus has been excluded from the API for the time being. + +## Prior Art +A few projects that implement Gateway API already have support for similar functionality (in their custom CRDs), like: +* Istio’s `VirtualService`: + +```yaml +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: reviews-route +spec: + hosts: + - reviews.prod.svc.cluster.local + http: + - headers: + request: + set: + test: "true" + route: + - destination: + host: reviews.prod.svc.cluster.local + subset: v2 + weight: 25 + - destination: + host: reviews.prod.svc.cluster.local + subset: v1 + headers: + response: + remove: + - foo + weight: 75 +``` + +* Contour’s `HTTPProxy`: + +```yaml +apiVersion: projectcontour.io/v1 +kind: HTTPProxy +metadata: + name: basic +spec: + virtualhost: + fqdn: foo-basic.bar.com + routes: + - conditions: + - prefix: / + services: + - name: s1 + port: 80 + responseHeadersPolicy: + set: + name: test + value: true +``` + +* Ingress NGINX: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: nginx-headers + annotations: + nginx.ingress.kubernetes.io/configuration-snippet: | + add_header ingress nginx; +spec: + ingressClassName: nginx + rules: + - host: custom.configuration.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: http-svc + port: + number: 80 +``` + +## External Links +* [Contour `HeaderValue`](https://projectcontour.io/docs/v1.22.0/config/api/#projectcontour.io/v1.HeaderValue) +* [Istio `Headers`](https://istio.io/latest/docs/reference/config/networking/virtual-service/#Headers) +* [Ingress NGINX Configuration Snippets](https://kubernetes.github.io/ingress-nginx/examples/customization/configuration-snippets/) +* [NGINX `add_header` directive](https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header) + diff --git a/site-src/ko/geps/gep-1323/metadata.yaml b/site-src/ko/geps/gep-1323/metadata.yaml new file mode 100644 index 0000000000..2f709a2b0f --- /dev/null +++ b/site-src/ko/geps/gep-1323/metadata.yaml @@ -0,0 +1,8 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1323 +name: Response Header Filter +status: Standard +authors: + - aryan9600 + diff --git a/site-src/ko/geps/gep-1324/1324-backend-ref.png b/site-src/ko/geps/gep-1324/1324-backend-ref.png new file mode 100644 index 0000000000..4d86942f73 Binary files /dev/null and b/site-src/ko/geps/gep-1324/1324-backend-ref.png differ diff --git a/site-src/ko/geps/gep-1324/1324-decomposed-view-of-service.png b/site-src/ko/geps/gep-1324/1324-decomposed-view-of-service.png new file mode 100644 index 0000000000..cc51a8fc6f Binary files /dev/null and b/site-src/ko/geps/gep-1324/1324-decomposed-view-of-service.png differ diff --git a/site-src/ko/geps/gep-1324/1324-resource-view-of-service.png b/site-src/ko/geps/gep-1324/1324-resource-view-of-service.png new file mode 100644 index 0000000000..a8d490fca4 Binary files /dev/null and b/site-src/ko/geps/gep-1324/1324-resource-view-of-service.png differ diff --git a/site-src/ko/geps/gep-1324/1324-service-frontend.png b/site-src/ko/geps/gep-1324/1324-service-frontend.png new file mode 100644 index 0000000000..e8aa31e6e2 Binary files /dev/null and b/site-src/ko/geps/gep-1324/1324-service-frontend.png differ diff --git a/site-src/ko/geps/gep-1324/index.md b/site-src/ko/geps/gep-1324/index.md new file mode 100644 index 0000000000..a80d6c8615 --- /dev/null +++ b/site-src/ko/geps/gep-1324/index.md @@ -0,0 +1,165 @@ +# GEP-1324: Service Mesh in Gateway API + +* Issue: [#1324](https://github.com/kubernetes-sigs/gateway-api/issues/1324) +* Status: Memorandum + +> **Note**: This GEP is exempt from the [Probationary Period][expprob] rules +> of our GEP overview as it existed before those rules did, and so it has been +> explicitly grandfathered in. + +[expprob]:../overview.md#probationary-period + +## Overview + +Gateway API represents the next generation of traffic routing APIs in Kubernetes. While most of the current work for Gateway API is focused on the ingress use-case, support for service mesh implementations within the spec would be advantageous to the greater community. Therefore, this GEP serves as the genesis for developing common patterns for using Gateway API for east/west traffic within a mesh implementation. + +## Goals + +* Augment the Gateway API specification with the necessary models, resources, and modifications so that the xRoute primitives are usable by service mesh implementations +* Make sure that Gateway API ingress implementations can coexist and interoperate with mesh implementations +* Remain agnostic as to the topology of mesh implementations’ data planes (i.e sidecar vs. non-sidecar) +* Enable mesh implementations to have vendor-specific extensions for their own policies, etc, in line with existing extensibility offered by Gateway API +* Cooperate with the greater Gateway API community on shared patterns/policies that are applicable for both use-cases (e.g. authorization policy) +* Maintain the integrity of the namespace boundary for traffic routing and policy, making explicit those instances where users define exceptions + +## Non-Goals + +* Represent every service mesh feature within Gateway API +* Duplicate concerns for the sake of “mesh-specific” resources +* Overload existing Gateway API mechanisms when a new mechanism is more appropriate +* Preemptively standardizing arbitrary policy attachment resources + * Will instead let these policies stay vendor specific and move for standardization once a pattern emerges organically + * N.B - vendors who implement common policies should strongly consider [namespacing](https://github.com/kubernetes-sigs/gateway-api/discussions/896#discussioncomment-1440319) their resources. More guidance to come + +## Versioning + +Features or other modifications to the Gateway API spec that fall under this GEP will be subject to the same [versioning guidelines](../../concepts/versioning.md#graduation-criteria) as the rest of the Gateway API. For example, to move changes concerning a beta feature (e.g. HTTPRoute) from experimental to standard, all of the [beta criteria](../../concepts/versioning.md#experimental-standard) must be met (e.g. implemented by several implementations). + +## Use-Cases + +These use-cases are presented as an aid for discussion, and as frames of reference for how users may attempt to utilize the outputs of this GEP. They are not an exhaustive list of features for mesh support in Gateway API nor does a particular use-cases inclusion necessarily imply that it is a goal. + +1. As a service producer… + 1. I want to deploy a canary version of my application that splits traffic based on HTTP properties. + 2. I want to change the behavior (such as timeouts, retries, header manipulation) of my application through configuration, rather than modifying my application. + 3. I want to apply authorization policies, using client identities and/or HTTP properties. + 4. I want to collect HTTP metrics for my application without modifying my application. + 5. I want to run a mix of protocols (HTTP, TCP, TLS, gRPC, …) within my application. + 6. I want to be able to gradually opt-in to a mesh (no mesh, L4 only, L7 enabled) so I can choose the right fit for my application's performance and compatibility goals. + 7. I want to define access policies for my service +2. As a service consumer… + 1. I want to change the behavior (such as timeouts, retries, header manipulation) when my application connects to services through configuration, rather than modifying my application. + 2. I want to collect HTTP metrics for services I connect to. + 3. I want to be able to connect to Kubernetes Services and external services. + 4. I want to override the destination of my traffic, for example, to send requests to external services to an internal replica, or to send all requests to an egress proxy. +3. As a mesh administrator… + 1. I want to enforce that all traffic within my cluster is encrypted. + 2. I want to have strict isolation and control at namespace level, so a bug/malicious user can't impact other namespaces + 3. I want to be able to allow app owners to gradually opt-in to a mesh (no mesh, L4 only, L7 enabled) so they can choose the right fit for their applications’ performance and compatibility goals. + 4. Since mesh can be multi-tenant and hosting multiple services (e.g. foo or bar), as a mesh administrator I need to make sure a client can discover different services. Here are a few possible ways: + 1. Each service is allocated a unique IP and port + 2. Or Each service must use a unique hostname + 3. Or a unique port and protocol (80:http, 443:tls) + +## Glossary + +When discussing design, it's helpful to have a shared vocabulary on the various relevant concepts. Many of these terms are highly overloaded or have many different meanings in different communities; the goal here is not to make any new standards or definitions, but rather to ensure readers are on the same page with important terms. + +### **Service Mesh** + +This is both core to the design and highly overloaded. Many folks have wildly different views of what "service mesh" means, and emotional responses to the word. For the purposes of this document, a "mesh" just means some component in a cluster that is capable of adding functionality to users network requests. The Gateway API for ingress traffic has been described as something that translates from things without context (outside of the cluster) to things with context (inside the cluster). Similarly, a service mesh could be described as something that uses that context to modify cluster network requests. + +This is intentionally broad - while most see a service mesh as "userspace sidecar proxies using iptables to redirect traffic", this document doesn't depend on this narrow definition, and includes architectures such as [Kubernetes itself](https://speakerdeck.com/thockin/weve-made-quite-a-mesh), ["proxyless" architectures](https://cloud.google.com/traffic-director/docs/proxyless-overview), and more. + +#### Scope of Functionality + +For the purposes of this feature, targeted service mesh functionality is limited to the following: + +1. Traffic routing (e.g. traffic splitting) +2. Traffic encryption + 1. Note that the implementation details of traffic encryption (e.g. mTLS, WireGuard) are out of the scope of this GEP. No specific implementation will be assumed. + +### **Policy** + +Policy is a broad term for any resource that can attach to another resource to configure it. This is defined in the [Policy Attachment GEP](../gep-713/index.md). Examples of (hypothetical) policies could be resources like `TimeoutPolicy` or `AuthorizationPolicy`. + +### **Routes** + +Routes are a collective term for a number of types in gateway-api: `HTTPRoute`, `TLSRoute`, `TCPRoute`, `UDPRoute`, etc. In the future there may be more defined, in core or extensions (such as `SQLRoute`).This document focuses on routes, rather than "Policy", as these are the primary existing core resources in gateway, and help form a foundation for policy attachment. Future work from GAMMA will likely look into policies, such as authorization policies. + +### **Service** + +"service" is a key component to meshes. In general mesh parlance, the term “service” represents an arbitrary cluster of related workloads accessible via the network as a single entity. In a Kubernetes world, this compute can be a typical `Service`, but it can also be something like a `ServiceImport` (from the MCS spec), or a custom type (a made up example would be a `CloudService` abstracting cloud endpoints). Due to the naming overlap with the Kubernetes `Service` resource, it becomes necessary to use more precise terms when describing these concerns, reserving `Service` exclusively for the Kubernetes resource. + +While a `Service` in Kubernetes is a single resource, logically it handles two different roles - a "**service frontend**" and "**service backend**". + +| Resource level view of Service | Decomposed view of Service | +|---|---| +| ![Resource level view of Service](images/1324-resource-view-of-service.png "Resource level view of Service") | ![Decomposed view of Service](images/1324-decomposed-view-of-service.png "Decomposed view of Service") | + +The "service frontend" refers to how we call a service. In a `Service`, this is an automatically allocated DNS name (`name.namespace.svc.cluster.local`) and IP address (`ClusterIP`). Not all services have frontends - for example, "headless" `Service`s. + +The "service backend" refers to the target of a service. In `Service`, this is `Endpoints` (or `EndpointSlice`). + +In the Gateway API today, `Service` is used as a "service backend". For example, in a route we would refer to `Service` as the (aptly named) `backendRef`: + +![image displaying how a route uses the backend function of a service](images/1324-backend-ref.png "image displaying how a route uses the backend function of the Service resource") + +A user connecting to a Gateway, which has a Route forwarding to "Service Backend" + +However, there are other ways that services _could_ be used in the API by utilizing the "service frontend". + +Below shows a hypothetical way to model splitting calls to the `a` service frontend to backends composed of `a-v1` and `a-v2` (see [real world example](https://linkerd.io/2.11/tasks/canary-release/)). In this case, service is used as both a frontend and a backend. The route attaches to "Service a frontend", and any calls to that will be directed to the `a-v1` and `a-v2` backends (as determined by the logic within the route. + +![image showing how a route could use the frontend function of the Service resource](images/1324-service-frontend.png "image showing how a route could use the frontend function of the Service resource") + +A user connecting to a service (frontend), which has a Route forwarding to two different services (backends) + +### **Producer** and **Consumer** + +A service **Producer** and service **Consumer** describe the two roles in a mesh. + +A service **producer** is someone that authors and operates a service. Some example actions they may take are deploy a `Service` and `Deployment`, setup authorization policies to limit access to their workloads, and setup routing rules to canary their workloads. + +A service **consumer** is someone that utilizes a service by communicating with it. For example, they may want to take actions like `curl hello-world` in their application - we could call this "consuming the `hello-world` service". + +Consumer and producer are personas, not concrete workloads or resources. One important aspect of these personas is that they may live in different trust boundaries (typically namespace). + +### **Gateway** + +We use the term “gateway” in reference to an abstract concept capturing the idea of a component which translates network traffic. + +We are using the term in a deliberately abstract way, therefore it is important that readers do not confuse this abstract interpretation of the term - and associated terms - with more concrete interpretations in more specific contexts. For example, we are specifically not referring to the meaning of “gateway” in IP packet routing, nor even the meaning of “translation” in that context. + +We can think of a gateway as being a component (aka “network element”) which implements a layer of indirection between a sender of traffic (e.g. a consumer) and its receivers (e.g. a producer). Senders and receivers are all known as “network endpoints”. Gateways consume +“reachability information” describing endpoints in order to gain knowledge of available receivers. + +We can describe the capabilities of this layer of indirection in various ways: + +* Routing - choosing a receiver endpoint based on data (routing discriminators like IP addresses, TCP/UDP ports, TLS SNI, HTTP headers, etc.) in the traffic and rules configured owners (or privileged users) of the gateway. +* Load-balancing - choosing a receiver endpoint from several valid endpoints based on knowledge of previous traffic from this or other sender endpoints, or knowledge of receiver endpoints status. +* Filtering - modifying the traffic in various ways before forwarding, for example modifying headers or URLs, or redirecting/mirroring the traffic to alternative endpoints. +* Encryption - some combination of decrypting traffic from sender endpoints and/or encrypting traffic before forwarding to receiver endpoints. + +A concrete implementation of these abstract ideas might modify traffic in the following ways: + +* Translation of IP addresses or TCP/UDP ports - the packet is forwarded after some address modifications (aka Network Address Translation, or NAT). +* Proxying of TCP/UDP packets or HTTP request/responses - the payload to be separated from the original protocol headers and new headers are constructed. A proxy acts as a server to receive traffic and as a client to forward the traffic onwards. +* Encapsulation of IP/TCP/UP packets in another protocol - the packet is wrapped in new protocol headers and must be de-encapsulated (“terminated”) by another gateway before being forwarded to the receiver endpoint. + +While a gateway may be a single-instance component through which traffic must flow - e.g. an IP router, or HTTP proxy - a gateway can also be deployed with multiple, redundant instances, or it can be a “logical” entity such that the traffic forwarding rules are distributed to many different parts of a network. Similarly, many “logical” gateway descriptions could potentially be combined or collapsed into a single concrete gateway configuration. + +Gateways are often used to “segment” endpoints on a network in various ways - we sometimes use “North/South” to describe traffic flowing across a segment boundary, and “East/West” to describe traffic flowing within a segment. Segmentation can be useful, for example, to separate tenants from one another to increase security. The concepts of “micro-segmentation” and “zero trust” describes the idea that security should be enforced even between trusted endpoints with a system, leading to smaller “micro” segments, even to the point of each endpoint occupying its own segment and trusting “zero” other endpoints. A gateway implements segmentation by being responsible for forwarding traffic between segments, and enforcing segmentation policy at that point. + +Gateways whose rule set describes how traffic should be translated as it “enters” a segment are known as “ingress gateways”. In contrast, gateways who provide some translation function to traffic leaving a segment are known as “egress gateways”. In other words, an ingress gateway is located on a segment boundary in front of service producers and an egress gateway is located on a segment boundary in front of service consumers. + +## Deferred Goals + +These are goals that we aren’t explicitly excluding, but will reconsider at a later point in time + +* Service mesh activation/enrollment (e.g. sidecar injection, namespace enrollment) +* Egress (e.g. off-mesh destinations including legacy services or third-party APIs) +* Multicluster use-cases (e.g. Kubernetes MCS or cluster federation) +* Heterogenous deployment targets (e.g VMs, serverless) +* Deployment models (e.g. installation, mesh upgrades) + diff --git a/site-src/ko/geps/gep-1324/metadata.yaml b/site-src/ko/geps/gep-1324/metadata.yaml new file mode 100644 index 0000000000..9e256c2d92 --- /dev/null +++ b/site-src/ko/geps/gep-1324/metadata.yaml @@ -0,0 +1,17 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1324 +name: Service Mesh in Gateway API +status: Memorandum +authors: + - keithmattix + - markmc + - kflynn +relationships: + extendedBy: + - number: 1426 + name: xRoutes Mesh Binding + description: Adds initial Service binding proposal + - number: 1686 + name: Mesh conformance testing plan + description: Adds initial Mesh conformance testing plan diff --git a/site-src/ko/geps/gep-1364/index.md b/site-src/ko/geps/gep-1364/index.md new file mode 100644 index 0000000000..681193f221 --- /dev/null +++ b/site-src/ko/geps/gep-1364/index.md @@ -0,0 +1,459 @@ +# GEP-1364: Status and Conditions Update + +* Issue: [#1364](https://github.com/kubernetes-sigs/gateway-api/issues/1364) +* Status: Standard + +## TLDR + +The status, particularly the Conditions, across the whole Gateway API have very much +grown organically, and so have many inconsistencies and odd behaviors. +This GEP covers doing a review and consolidation to make Condition behavior consistent +across the whole API. + +## Goals + +* Update Conditions design to be consistent across Gateway API resources +* Provide a model and guidelines for Conditions for future new resources +* Specify changes to conformance required for Condition updates + +## Non-Goals + +* Define the full set of Conditions that will ever be used with Gateway API + +## Introduction + +Gateway API currently has a lot of issues related to status, especially that +status is inconsistent ([#1111][1111]), that names are hard to understand ([#1110][1110]), +and that Reasons aren't explained properly ([#1362][1362]). + +As the API has grown, the way we talk about resources has changed a lot, and some of the +status design hasn't been updated since resources were created. + +So, for example, we have GatewayClass with `Accepted`, Gateway with `Scheduled`, +the Gateway Listeners with `Detached` (which you want to be `false`, unlike the previous +two), and then Gateways and Gateway Listeners have `Ready`, but Route doesn't (and which +also you want to be `true`). + +This document lays out large-scale changes to the way that we talk about resources, +and the Conditions to match them. This means that there will be an unavoidable break +in what constitutes a healthy or unhealthy resource, and there will be changes +required for all implementations to be conformant with the release that includes +these changes. + +The constants that mark the deprecated types will be also marked as deprecated, +and will no longer be tested as part of conformance. They'll still be present, +and will work, but they won't be part of the spec anymore. This should give +implementations and users a release to transition to the new design (in UX terms). +This grace period should be one release (so, the constants will be removed in +v0.7.0.) + +This level of change is not optimal, and the intent is to make this a one-off change +that can be built upon for future resources - since there are definitely more resources +on the way. + +## Background: Kubernetes API conventions and prior art on Conditions + +Because this GEP is mainly concerned with updating the Conditions we are setting in +Gateway API resources' `status`, it's worth reviewing some important points about +Conditions. (This information is mainly taken from the [Typical status properties][typstatus] +section of the API conventions document.) + +1. Conditions are a standard type used to represent arbitrary higher-level status from +a controller. +2. They are a listMapType, a list that is enforced by the apiserver to have only +one entry of each item, using the `type` field as a key. (So, this is effectively +a map that looks like a list in YAML form). +3. Each has a number of fields, the most important of which for this discussion +are `type`, `status`, `reason`, and `observedGeneration`. + + * `type` is a string value indicating the Condition type. `Accepted`, `Scheduled`, + and `Ready` are current examples. + * `status` indicates the state of the condition, and can be one of three values, + `true`, `false`, or `unknown`. Unknown in particular is important, because it + means that the controller is unable to determine the status for some reason. + (Also notable is that "" is also valid, and must be treated as `Unknown`. + Controllers must not set the value to "", but consumers should accept it + as meaning the same thing as `Unknown`.) + * `reason` is a CamelCase string that is a brief description of the reason why + the `status` is set the way it is. + * `observedGeneration` is an optional field that sets what the `metadata.generation` + field was when the controller last saw a resource. Note that this is optional + _in the struct_, but is required for Gateway API conditions. This will be + enforced in the conformance tests in the future. + +4. Conditions should describe the _current state_ of the resource at observation +time, which means that they should be an adjective (like `Ready`), or a past-tense +verb (like `Accepted`). This one in particular is documented pretty closely in the +[Typical status properties][typstatus] section of the guidelines. +5. Conditions should be applied to a resource the first time the controller sees +the resource. This seems to imply that _all conditions should be present on every +resource owned by a controller_, but the rest of the conventions don't make this +clear, and it is often not complied with. +6. It's helpful to have a top-level condition which summarizes more detailed conditions. +The guidelines suggest using either `Ready` for long-running processes, or `Succeeded` +for bounded execution. + +From these guidelines, we can see that Conditions can be either _positive polarity_ +(healthy resources have them as `status: true`) or _negative polarity_ (healthy +resources have them as `status: false`). `Ready` is an example of a positive polarity +condition, and conditions like `Conflicted` from Listener or `NetworkUnavailable`, +`MemoryPressure`, or `DiskPressure` from the Node resource are examples of +negative-polarity conditions. + +There is also some extra context that's not in the API conventions doc: + +SIG-API Machinery has been reluctant to add fields that would aid in machine-parsing +of Conditions, especially fields that would indicate the polarity, because they +are intended more for human consumption than machine consumption. Probably the best +example of this was in the PR [#4521](https://github.com/kubernetes/community/pull/4521#issuecomment-64894206). + +This means that there's no guidance from upstream about condition polarity. We'll +discuss this more when we talk about new conditions. + +The guidance about Conditions being added as soon as a controller sees a resource +is a bit unclear - as written in the conventions, it seems to imply that _all_ +relevant conditions should always be added, even if their status has to be set to +`unknown`. +Gateway API resources do not currently require this, and the practice seems to be +uncommon. + +## Proposed changes + +### Proposed changes summary + +* All the current Conditions that indicate that the resource is okay and ready +for processing will be replaced with `Accepted`. +* In general, resources should be considered `Accepted` if their config is valid +enough to generate some config in the underlying data plane. Examples are provided +below. +* There will be a limited set of positive polarity summary conditions, and a number +of other specific negative-polarity error conditions. +* All relevant positive-polarity summary Conditions for a resource must be added +when it's observed. +For example, HTTPRoutes must always have `Accepted` and `ResolvedRefs`, regardless +of their state. +* Negative polarity error conditions must only be added when the error is True. +* The `Ready` condition will be moved to Extended conformance, and we'll re-evaluate +if it's used by any implementations after some time has passed. If not, it may be +removed. +* To capture the behavior that `Ready` currently captures, `Programmed` will be +introduced. This means that the implementation has seen the config, has everything +it needs, parsed it, and sent configuration off to the data plane. The configuration +should be available "soon". We'll leave "soon" undefined for now. +* Resolving a comment that came up, documentation will be added to clarify that +it's okay to add your own Conditions, and that implementations should namespace +their custom Conditions with a domain prefix (so `implementation.io/CustomType` +rather than just `CustomType`), or run the risk of using a word that's reserved later. +* It's recommended that implementations publish both new and old conditions to +provide a smoother transition, but conformance tests will only require the new +conditions. + +The exact list of changes is detailed below. The next few sections detail +the reasons for these large-scale changes. + +### Conceptual and language changes + +Gateway API resources are, conceptually, all about breaking up the configuration for a +data plane into separate resources that are _expressive_ and _extensible_, while being +split up along _role-oriented_ boundaries. + +So, when we talk about Gateway API, it's _always_ about a _system of related resources_. + +We already acknowledge this when we talk about Routes "attaching" to Gateways, or Gateways +referencing Services, or Gateways requiring a GatewayClass in their spec. + +However, this GEP is proposing that we move all our discussion into using +"accepted" to indicate that a resource has attached correctly enough to be +_accepted_ for processing. + +So resources are `Accepted` for processing when their attachment succeeds enough +to generate some configuration. This allows us to make calls about when partially +valid objects should be accepted and when they shouldn't. + +Of course, because we're using all of this configuration to describe some sort of data +path from "outside"/lacking cluster context to "inside"/enriched with cluster context, +we also need a way to describe when that data path is configured and working. + +We already have a word in the Kubernetes API, but it comes with some expectations +that implementations are not currently able to meet. That word is `Ready`, but it +implies that the data path is Ready _when you read the status_, rather than that +it _will be ready soon_ (which is what most implementations can guarantee currently.) + +So we have an unresolved question as to what to do with the `Ready` condition. +This is addressed further below. + +### Condition polarity + +In terms of the polarity of conditions, we have three options, of which only two are +really viable: +* All conditions must be negative polarity +* All conditions must be positive polarity +* Some conditions can be positive polarity, but most should be negative. + +The fact that the user experience of `Ready` or conditions like `Accepted` being `true` +in the healthy case is much better rules out the first option, so we are left to +decide between enforcing that all conditions are positive, or that we have a mix. + +Having an arbitrary mix will make doing machine-based extraction of information +much harder, so here I'm going to talk about the distinction between having all +conditions positive or some, summary conditions positive, and the rest negative. + +#### All Conditions Positive + +In this case, all Condition types are written in such a way that they're positive +polarity, and are `true` in the healthy case. + +As already discussed, `Ready`, and `Accepted` are current examples, but another +one that's a little more important here is `ResolvedRefs` which is set to `true` +when all references to other resources have been successfully resolved. This is +not a _blocking_ Condition that affects the `Ready` condition, since having _some_ +references valid is enough to produce some configuration in the underlying data +plane. + +So, All Conditions Positive pros: + +* We're close already. Most conditions in the API are currently positive polarity. +* Easier to understand - there are no double negatives. "Good: true" is less +cognitive overhead than "NotGood: false". + +Cons: + +* Reduces flexibility - it can surprisingly difficult to avoid double negatives for +conditions that describe error states, as in general programmers are more used +to reporting "something went wrong" than they are "everything's okay". + +Not sure if pro or con: + +* Leans the design towards favoring conditions always being present, since you +can't be sure if everything is good unless you see `AllGood: true`. The absence +of a positive-polarity condition implies that the condition could be false. This +puts this option more in line with the API guidelines on this point. + +#### Some Conditions Positive + +In this case, only a limited set of summary conditions are positive, and the rest +are negative. + +Pros: + +* Error states can be described with `Error: true` instead of `NoError: false`. +* Negative polarity error conditions are more friendly to not being present (since +absence of `Error: true` implies everything's okay). + +Cons: + +* Any code handling conditions will need a list of the positive ones, and will +need to assume that any others are negative. + +#### Decision + +Gateway API conditions will be positive for conditions that describe the happy +state of the object, which is currently `Accepted` and `ResolvedRefs`, and will +also include the new `Programmed` condition, and the newly-Extended condition +`Ready`. A separate set of negative-polarity Error conditions will be set on an +object when they are true. + + +### Should conditions always be added? + +Not all of them. + +Positive polarity Conditions that describe the desirable state of the object must +always be set. These are currently `Accepted`, `ResolvedRefs`, and `Programmed`. +Implementations that use `Ready` must also add it before programming the Route. + +### Partial validity and Conditions + +One of the trickiest parts of Gateway API objects is that it's very possible to +end up with an object that has some parts with valid configuration and some that +don't. We refer to this as _partial validity_, and communicating this via status +conditions is difficult. + +The intent with the `Accepted` condition is that it serves as an indicator that +_something_ is working, that _some traffic_ from what the config specifies will +be routed as configured. + +At this time, we haven't added a "no errors at all present" Condition, choosing +to have a "some config is working" condition, with specific errors to aid in +finding the exact problem with the objects. We could conceivably add this later +if users find `Accepted` insufficient, but we're erring on the side of having +less positive Conditions for now. + +### New and Updated Conditions + +#### `Accepted` + +This GEP proposes replacing all conditions that indicate syntactic and semantic +validity with one, `Accepted` condition type. + +That is, the proposal is to replace: + +* `Scheduled` on Gateway +* `Detached` on Listener + +with `Accepted` in all these locations. + +GatewayClass and Route will maintain the `Accepted` condition. + +All of these conditions share the following meanings: + +* The resource has been accepted for processing by the controller +* The resource is syntactically and semantically valid, and internally consistent +* The resource fits into a larger system of Gateway API resources, and there is +is no missing information, including but not limited to: + * Any mandatory references resolve to existing resources (examples here are the + Gateway's gatewayClass field, or the `parentRefs` field in Route resources) + * Any specified TLS secrets exist +* The resource is supported by the controller by ensuring things like: + * Any Kinds being referred to by the resource are supported + * Features being used by the resource are supported + +All of these rules can be summarized into: + +* The resource is valid enough to produce some configuration in the underlying +data plane. + +For Gateway, `Accepted` also subsumes the functions of `Scheduled`: `Accepted` +set to `true` means that sufficient capacity exists on underlying infrastructure +for the Gateway to be provisioned. If that capacity does not exist, then the +Gateway cannot be reconciled successfully, and so fails to attach to the +owning GatewayClass, and cannot be accepted. + +Note that some classes of inter-resource reference failure do _not_ cause a resource +to become unattached and stop being accepted (that is, to have the `Accepted` +condition set to `status: false`). + +* Nonexistent Service backends - if the backend does not exist on a HTTPRoute that +is otherwise okay, then the data plane must generate 500s for traffic that matches +that HTTPRoute. In this case, the `Accepted` Condition must be true, and the +`ResolvedRefs` Condition must be false, with reasons and messages indicating that +the backend services do not exist. +* HTTPRoutes with *all* backends in other namespaces, but not permitted by ReferenceGrants. +In this case, the "nonexistent service backends" rules apply, and 500s must be +generated. In this case, again, the `Accepted` condition is true, and the +`ResolvedRefs` Condition is false, with reasons and messages indicating that the +backend services are not reachable. + +For ReferenceGrant or not-designed-yet Policy resources, `Accepted` means that: + +* the resource has a correctly-defined set of resources that it applies to +* the resource has a syntactically and semantically valid `spec` + +Note that having a correctly-defined set of resources that is empty does not make +these resources unattached, as long as it's possible to create some config in the +underlying data plane. By "empty" here we mean that there are no backends, +not that the config is incomplete or missing references. So you can have a +GatewayClass, Gateway, HTTPRoute and Service all present and referred to correctly +when there are no endpoints in the Service, and the resource will not stop being +accepted, because HTTPRoute contains rules about what to program in the data plane +if there are no endpoints (that is, it should return 500 for any matching request). + +Note that for other Route types that don't have a clear mechanism like HTTP does +for indicating a server failure (like the HTTP code 500 does), not having existing +backends may not produce any configuration in the data plane, and so may cause +the resource to fail to attach. (An example here could be a TCP Route with +no backends, we need to decide if that means that a port should be opened that +actively closes connections, or if no port should be opened.) + +Examples of Conditions: + +* HTTPRoute with one match with one backend that is valid. `Accepted` is true, +`ResolvedRefs` is true. +* HTTPRoute with one match with one backend that is a nonexistent Service backend. +The `Accepted` Condition is true, the `ResolvedRefs` condition is false, with +a reason of `BackendNotFound`. `Accepted` is true in this case because the data +path must respond to requests that would be sent to that backend with a 500 response. +* HTTPRoute with one match with two backends, one of which is a nonexistent Service +backend. The `Accepted` Condition is true, the `ResolvedRefs` condition is false. +`Accepted` is true in this case because the data path must respond to a percentage +of the requests matching the rule corresponding to the weighting of the nonexistent +backend (which would be fifty percent unless weights are applied). +* HTTPRoute with one match with one backend that is in a different namespace, and +does _not_ have a ReferenceGrant permitting that access. The `Accepted` condition +is true, and the `ResolvedRefs` Condition is false, with a reason of `RefNotPermitted`. +As before, `Accepted` is true because in this case, the data path must be +programmed with 500s for the match. +* TCPRoute with one match with a backend that is a nonexistent Service. `Accepted` +is false, and `ResolvedRefs` is false. `Accepted` is false in this case because +there is not enough information to program any rules to handle the traffic in the +underlying data plane - TCP doesn't have a way to say "this is a valid destination +that has something wrong with it". +* HTTPRoute with one Custom supported filter added that is not supported by the +implementation. Our spec is currently unclear on what happens in this case, but +custom HTTP Filters require the use of the `ExtensionRef` filter type, and the +setting of the ExtensionRef field to the name, group, version, and kind of a +custom resource that describes the filter. If that custom resource is not supported, +it seems reasonable to say that this should be a reference failure, and be treated +like other reference failures (`Accepted` will be set to true, `ResolvedRefs` to +false with a `InvalidKind` Reason, and traffic that would have matched the filter +should receive a 500 error.) +* A HTTPRoute with one rule that specifies a HTTPRequestRedirect filter _and_ a +HTTPURLRewrite filter. `Accepted` must be false, because there's only one rule, +and this configuration for the rule is invalid (see [reference][httpreqredirect]) +The error condition in this case is undefined currently - we should define it, +thanks @sunjayBhatia. +* A HTTPRoute with two rules, one valid and one which specifies a HTTPRequestRedirect +filter _and a HTTPURLRewrite filter. `Accepted` is true, because the valid rule +can produce some config in the data plane. We'll need to raise the more specific +error condition for an incompatible filter combination as well to make the partial +validity clear. + + +#### Ready + +Currently, the `Ready` condition text for Gateway says: +```go + // This condition is true when the Gateway is expected to be able + // to serve traffic. Note that this does not indicate that the + // Gateway configuration is current or even complete (e.g. the + // controller may still not have reconciled the latest version, + // or some parts of the configuration could be missing). +``` + +This is pretty unclear - how can the Gateway serve traffic if config is missing? +In the past, we've been asked to have a Condition that only flips to `true` when +*all* required configuration is present. + +For many implementations (certainly for Envoy-based ones), getting this information +correctly and avoiding races on applying it is surprisingly difficult. + +For this reason, this GEP proposes that we exclude the `Ready` condition from Core +conformance, and make it a feature that implementations may opt into - making it +an Extended condition. + +It will have the following behavior: + +* `Ready` is an optional Condition that has Extended support, with conformance +tests to verify the behavior. +* When it's set, the condition indicates that traffic is ready to flow through +the data plane _immediately_, not at some eventual point in the future. + +We'll need to add conformance testing for this. + +#### Programmed + +The `Programmed` condition is being added to replicate the functionality that the +`Ready` condition currently indicates, namely that all the resources in the set +are valid enough to produce some data plane configuration, and that configuration +has been sent to the data plane, and should be ready soon. + +It is a positive-polarity summary condition, and so should always be present on +the resource. It should be set to `Unknown` if the implementation performs updates +to the status before it has all the information it needs to be able to determine +if the condition is true. + + +## Alternatives + +(Most alternatives have been discussed inline. Please comment here if this section +needs updating.) + +## References +[kep-status]: https://github.com/kubernetes/enhancements/blob/master/keps/NNNN-kep-template/kep.yaml#L9 + +[1111]: https://github.com/kubernetes-sigs/gateway-api/issues/1111 +[1110]: https://github.com/kubernetes-sigs/gateway-api/issues/1110 +[1362]: https://github.com/kubernetes-sigs/gateway-api/issues/1362 + +[typstatus]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties +[httpreqredirect]: ../../reference/spec.md#gateway.networking.k8s.io%2fv1beta1.HTTPRequestRedirectFilter diff --git a/site-src/ko/geps/gep-1364/metadata.yaml b/site-src/ko/geps/gep-1364/metadata.yaml new file mode 100644 index 0000000000..7629aabf02 --- /dev/null +++ b/site-src/ko/geps/gep-1364/metadata.yaml @@ -0,0 +1,7 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1364 +name: Status and Conditions Update +status: Standard +authors: + - youngnick diff --git a/site-src/ko/geps/gep-1494/index.md b/site-src/ko/geps/gep-1494/index.md new file mode 100644 index 0000000000..5d5991052f --- /dev/null +++ b/site-src/ko/geps/gep-1494/index.md @@ -0,0 +1,160 @@ +# GEP-1494: HTTP Auth in Gateway API + +* Issue: [#1494](https://github.com/kubernetes-sigs/gateway-api/issues/1494) +* Status: Provisional + +(See [status definitions](../overview.md#gep-states).) + + +## TLDR + +Provide a method for configuring **Gateway API implementations** to add HTTP Authentication for north-south traffic. The method may also include Authorization config if practical. At the time of writing, this authentication is only for ingress traffic to the Gateway. + + +## Goals + +(Using the [Gateway API Personas](../../concepts/roles-and-personas.md)) + +* A way for Ana the Application Developer to configure a Gateway API implementation to perform Authentication (at least), with optional Authorization. + +* A way for Chihiro the Cluster Admin to configure a default Authentication and/or Authorization config for some set of HTTP or GRPC matching criteria. + +## Stretch Goals + +* Optionally, a way for Ana to have the ability to disable Authentication and/or Authorization for specific routes when needed, allowing certain routes to not be protected. This would probably need to work something like a default enabling at Gateway level, that can be specifically set at lower levels, but further design is TBD. This goal comes from the relatively-common desire for Chihiro to be able to set reasonably-secure defaults, and for Ana or others to be able to _disable_ for specific paths for purposes of health checks. The fact that this is relatively undefined is why this goal is _optional_. + + +## Non-Goals + +* Handling all possible authentication and authorization schemes. Handling a (preferably large) subset of authentication and authorization is acceptable. + + +## Deferred Goals + +* (Not performed during the Provisional Phase) Defining the API or configuration to be used. +* Handling GRPC (We will handle plain HTTP first) +* Any decisions about doing Auth for non-HTTP protocols (this is a whole other problem that could significantly impact timelines) + +## Introduction + +A common request for Gateway API has been a way to direct implementations to automatically request various forms of authentication and authorization. (see the [GEP Issue](https://github.com/kubernetes-sigs/gateway-api/issues/1494) for some of the history.) + +**Authentication (AuthN for short)** refers to proving the requesting party's identity in some fashion. + +**Authorization (AuthZ for short)** refers to making decisions about what a party can access _based on their Authenticated identity_. + +In this document, we'll use Auth* to represent "AuthN and maybe AuthZ as well". + +This capability is useful for both Ana (who wants to have something for AuthN and AuthZ that ensures security without it needing to be built into her app), and Chihiro (who wants to be able to ensure that the platform as a whole conforms to some given level of security). + +### Common authentication methods + +Before discussing any proposed Auth* solution, it's important to discuss some AuthN methods that are often used in securing modern applications. + +#### Basic HTTP Auth + +In Basic HTTP Auth, a server asks for authentication as part of returning a `401` status response, and the client includes an `Authorization` header that includes a Base64-encoded username and password. + +Use of passwords in this way is very vulnerable to replay attacks (since if you get the password, you can use +it as many times as you like), which is why Basic Auth is generally used for lower-security use cases. + +However, even in the lowest-security use cases, using TLS to at least prevent man-in-the-middle password interception is very necessary. + +Basic auth is defined in [RFC-7617](https://datatracker.ietf.org/doc/html/rfc7617). + +#### TLS Client Certificate Authentication + +TLS includes the possibility of having both the client and server present certificates for the other party to validate. (This is often called "mutual TLS", but is distinct from the use of that term in Service Mesh contexts, where it means something more like "mutual TLS with short-lifetime, automatically created and managed dynamic keypairs for both client and server"). + +In this case, the server also authenticates the client, based on the certificate chain presented by the client. Some implementations also allow details about the certificate to be passed through to backend clients, to be used in authorization decisions. + +TLS v1.3 is defined in [RFC-8446](https://datatracker.ietf.org/doc/html/rfc8446), with v1.2 defined in [RFC-5246](https://datatracker.ietf.org/doc/html/rfc5246). Earlier versions of TLS (v1.1 and v1.0) were deprecated in [RFC-8996](https://datatracker.ietf.org/doc/html/rfc8996) and should no longer be used. + +Gateway API already has some work in progress to handle this for straightforward use cases, in [GEP-91](../gep-91/index.md). + +#### JWT + +JWT is a format for representing _claims_, which are stored as fields in a JSON object. In common use, these claims represent various parameters that describe the properties of an authentication, with sample claims being `iss`, Issuer, `sub`, Subject, and `aud`, Audience. + +JWT also specified ways in which JWTs can be _nested_, where a JWT is encoded inside another JWT, which allows the use of encryption and signing algorithms. In the Gateway API Auth* case, this is expected to be common, in a pattern looking something like this: + +- a common authority issues keypairs to clients and servers +- clients include JWTs with requests that identify themselves and their intended uses +- servers unwrap encryption and validate signatures of these JWTs to validate the chain of trust +- servers use the authentication details to make authorization decisions. + +JWT is defined in [RFC-75199](https://datatracker.ietf.org/doc/html/rfc7519). + +#### Oauth2 and OIDC + +Oauth2 is an _authorization framework_, which allows clients and servers to define ways to perform authentication and authorization in as secure a way as possible. It extensively uses TLS for encryption, and involves a third-party handling the authorization handshake with a client, which the third-party then provides to the server. + +Open ID Connect (OIDC) is a protocol based on the OAuth 2 framework, that allows Users to talk to Identity Providers (IDPs), on behalf of a Relying Party (RP), and have the IDP give the user an Identity Token (which the User's browser can then provide as Authentication to the Relying Party), and also allows the RP to request Claims about the User, which can be used for Authorization. + +Usually, the Identity Token is delivered using JWT, although that is not required. + +## Auth* User Stories + + +* As Ana the Application Developer, I wish to be able to configure that some or all of my service exposed via Gateway API requires Authentication, and ideally to be able to make Authorization decisions about _which_ authenticated clients are allowed to access. +* As Ana the Application Developer, I wish to be able to redirect users to a login page when they lack authentication, while unauthenticated API access gets the proper 40x response. +* As Chihiro the Cluster Admin, I wish to be able to configure default Authentication settings (at least), with an option to enforce Authentication settings (preferable but not required) for some set of services exposed via Gateway API inside my cluster. +* More User Stories welcomed here! + +## Currently implemented Auth mechanisms in implementations + +Many Gateway API implementations have implemented some method of configuring Auth* that are either delivered outside of the Gateway API framework, or if they are inside, are currently Implementation Specific. + +This section lays out some examples (updates with extra examples we've missed are very welcome). + +#### HTTP Authentication +| Name | External Authentication | Self Authentication | +| -------- | -------- | -------- | +| [HAProxy Ingress](https://haproxy-ingress.github.io/docs/configuration/keys/) | [Custom](https://haproxy-ingress.github.io/docs/configuration/keys/#auth-external) , [OAuth](https://haproxy-ingress.github.io/docs/configuration/keys/#oauth) | [Basic](https://github.com/jcmoraisjr/haproxy-ingress/tree/master/examples/auth/basic), [mTLS](https://haproxy-ingress.github.io/docs/configuration/keys/#auth-tls) | +|[GlooEdge](https://docs.solo.io/gloo-edge/latest/guides/security/auth/extauth/)| [Envoy](https://github.com/solo-io/gloo) ( [Basic](https://docs.solo.io/gloo-edge/latest/guides/security/auth/extauth/basic_auth/), [passthrough](https://docs.solo.io/gloo-edge/latest/guides/security/auth/extauth/passthrough_auth/), [OAuth](https://docs.solo.io/gloo-edge/latest/guides/security/auth/extauth/oauth/), [ApiKey](https://docs.solo.io/gloo-edge/latest/guides/security/auth/extauth/apikey_auth/), [LDAP](https://docs.solo.io/gloo-edge/latest/guides/security/auth/extauth/ldap/), [Plugin](https://docs.solo.io/gloo-edge/latest/guides/security/auth/extauth/plugin_auth/)), [Custom](https://docs.solo.io/gloo-edge/latest/guides/security/auth/custom_auth/) | Envoy ([JWT](https://docs.solo.io/gloo-edge/latest/guides/security/auth/jwt/)) +|[traefik](https://doc.traefik.io/traefik/middlewares/http/forwardauth/)|[Custom(ForwardAuth middleware)](https://doc.traefik.io/traefik/middlewares/http/forwardauth/)|[Basic](https://doc.traefik.io/traefik/middlewares/http/basicauth/), [Digest Auth](https://doc.traefik.io/traefik/middlewares/http/digestauth/)| +|[Ambassador](https://www.getambassador.io/docs/edge-stack/latest/howtos/ext-filters)|[Envoy](https://github.com/emissary-ingress/emissary) ([Basic](https://www.getambassador.io/docs/edge-stack/latest/howtos/ext-filters#2-configure-aesambassador-edge-stack-authentication))|[SSO(OAuth, OIDC)](https://www.getambassador.io/docs/edge-stack/latest/howtos/oauth-oidc-auth) | +|[ingress-nginx](https://kubernetes.github.io/ingress-nginx/examples/customization/external-auth-headers/)|[httpbin](https://httpbin.org) ([Basic](https://kubernetes.github.io/ingress-nginx/examples/auth/external-auth/), [OAuth](https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/))|[Basic](https://kubernetes.github.io/ingress-nginx/examples/auth/basic/), [Client Certificate](https://kubernetes.github.io/ingress-nginx/examples/auth/client-certs/)| +|[Envoy](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto)|[External Authorization server (ext_authz filter)](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto) |[JWT](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/jwt_authn/v3/config.proto)| +|[Contour](https://projectcontour.io/docs/1.24/config/client-authorization/)|[Envoy](https://projectcontour.io/docs/1.24/config/client-authorization/)|[Envoy(JWT)](https://projectcontour.io/docs/1.24/config/jwt-verification/)| +|[Istio](https://istio.io/latest/docs/tasks/security/authorization/)|[mutual TLS ingress gateway](https://istio.io/latest/docs/tasks/traffic-management/ingress/secure-ingress/#configure-a-mutual-tls-ingress-gateway), [External Authorization](https://istio.io/latest/docs/tasks/security/authorization/authz-custom/)|[JWT (RequestAuthentication)](https://istio.io/latest/docs/reference/config/security/request_authentication/)| +|[Envoy Gateway](https://gateway.envoyproxy.io/docs/tasks/security/ext-auth/)| [Envoy](https://gateway.envoyproxy.io/docs/tasks/security/ext-auth/#http-external-authorization-service) | [Envoy(JWT)](https://gateway.envoyproxy.io/docs/tasks/security/jwt-authentication/), [Basic](https://gateway.envoyproxy.io/docs/tasks/security/basic-auth/) | +|[Consul](https://developer.hashicorp.com/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s)|[Envoy](https://developer.hashicorp.com/consul/docs/connect/proxies/envoy-extensions/configuration/ext-authz)| [JWT](https://developer.hashicorp.com/consul/docs/connect/gateways/api-gateway/secure-traffic/verify-jwts-k8s#use-jwts-to-verify-requests-to-api-gateways-on-kubernetes)| + + +## Outstanding Questions and Concerns (TODO) + +From @ongy, some additional goals to keep in mind: +* The API of the proposed implementation provides enough flexibility to integrate with an authorization mechanism and protect resources entirely in the gateway +* The API allows to inject information about the authentication result into the requests and allows backend application to make authorization decisions based on this. + +## API + +(... details, can point to PR with changes) + +## Conformance Details + +(from https://github.com/kubernetes-sigs/gateway-api/blob/main/geps/gep-2162/index.md#standardize-features-and-conformance-tests-names) + +#### Feature Names + +Every feature should: + +1. Start with the resource name. i.e HTTPRouteXXX +2. Follow the PascalCase convention. Note that the resource name in the string should come as is and not be converted to PascalCase, i.e HTTPRoutePortRedirect and not HttpRoutePortRedirect. +3. Not exceed 128 characters. +4. Contain only letters and numbers + +### Conformance tests + +Conformance tests file names should try to follow the `pascal-case-name.go` format. +For example for `HTTPRoutePortRedirect` - the test file would be `httproute-port-redirect.go`. +Treat this guidance as "best effort" because we might have test files that check the combination of several features and can't follow the same format. +In any case, the conformance tests file names should be meaningful and easy to understand. + +## Alternatives + +(List other design alternatives and why we did not go in that +direction) + +## References diff --git a/site-src/ko/geps/gep-1494/metadata.yaml b/site-src/ko/geps/gep-1494/metadata.yaml new file mode 100644 index 0000000000..14161d8cb4 --- /dev/null +++ b/site-src/ko/geps/gep-1494/metadata.yaml @@ -0,0 +1,19 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1494 +name: HTTP Auth in Gateway API +status: Provisional +# Any authors who contribute to the GEP in any way should be listed here using +# their GitHub handle. +authors: + - youngnick + - jgao1025 +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: {} +# featureNames is a list of the feature names introduced by the GEP, if there +# are any. This will allow us to track which feature was introduced by which GEP. +featureNames: {} +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: {} diff --git a/site-src/ko/geps/gep-1619/index.md b/site-src/ko/geps/gep-1619/index.md new file mode 100644 index 0000000000..04451eb948 --- /dev/null +++ b/site-src/ko/geps/gep-1619/index.md @@ -0,0 +1,1234 @@ +# GEP-1619: Session Persistence via BackendLBPolicy + +* Issue: [#1619](https://github.com/kubernetes-sigs/gateway-api/issues/1619) +* Status: Experimental + +(See [status definitions](../overview.md#gep-states).) + +## Graduation Criteria + +### Implementable + +This GEP was accidentally merged as Provisional before the required approval +from 2 maintainers had been received. Before this graduates to implementable, +we need to get at least one of @robscott or @youngnick to also approve this GEP. + +Before this GEP graduates to Implementable, we must fulfill the following criteria: + + 1. Should we leave room in this policy to add additional concepts in the future + such as Session Affinity? If so, how would we adjust the naming and overall + scope of this policy? + - **Answer**: Yes. We adjusted the API to use `BackendLBPolicy`. See [API](#api) for more details. + 2. Should we leave room for configuring different forms of Session Persistence? + If so, what would that look like? + - **Answer**: Yes. See the [BackendLBPolicy API](#BackendLBPolicy-api) and [API Granularity](#api-granularity) + sections for more details. + 3. What name appropriately describe the API responsible for configuring load-balancing options for backend traffic? + - **Answer**: We decided on `BackendLBPolicy` since it is aligned with `BackendTLSPolicy`, describes configuration + related to load balancing, and isn't too long. + 4. Finish designing the [Route Rule API](#route-rule-api) and document edge cases in [Edge Case Behavior](#edge-case-behavior) + for configuring session persistence on both `BackendLBPolicy` and route rules. + - **Answer**: Yes. See [Route Rule API](#route-rule-api) and [Edge Case Behavior](#edge-case-behavior) for more details. + +### Standard + +Before this GEP graduates to the Standard channel, we must fulfill the following criteria: + +- Sign-off from the GAMMA leads to ensure service mesh gets fully considered. + +## TLDR + +This GEP initially proposes a definitions for session persistence, followed by the definition of an API spec for +configuring it. Additionally, it explores example scenarios of session persistence and examines the approaches that +implementations have taken to design APIs for session persistence. It intentionally refrains from defining an API for +session affinity, as this design is expected to be addressed within a separate GEP. + +## Goals + +- Define session persistence and session affinity to establish a common language +- Identify differences in session persistence functionality between implementations +- Define an API for session persistence +- Establish anticipated outcomes for specific API configurations or scenarios + +## Non-Goals + +- Define an API for session affinity +- Mandate a default session persistence or session affinity functionality for implementations +- Prescribe the precise manner (the "how") in which implementations should achieve session persistence or handle + specific scenarios +- Add API configuration for supporting backend initiated sessions + +## Introduction + +### Naming + +Naming is hard. We've had lots of [discussion](https://github.com/kubernetes-sigs/gateway-api/discussions/2893) on the +topic of naming session persistence. Adding to the complexity, the Gateway API implementations do not have a consensus +on a naming convention for session persistence or affinity. + +To start this discussion, lets establish the idea of strong session affinity (what this GEP calls session persistence) +and weak session affinity (what this GEP calls session affinity) which we will define further in +[The Relationship of Session Persistence and Session Affinity](#the-relationship-of-session-persistence-and-session-affinity). +In this context, "strong" implies a guarantee, while "weak" indicates a best-effort approach. + +Here's a survey of how some implementations refers to these ideas: + +| Implementation | Name for Strong Session Affinity | Name for Weak Session Affinity | +| ------------- | ------------- | ------------- | +| Apache APISIX | [Sticky Sessions](https://apisix.apache.org/docs/ingress-controller/concepts/apisix_upstream/) | N/A | +| Avi Kubernetes Operator | [Session Persistence](https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/administration/GUID-8B5C8D64-2B69-4C95-86A5-C5396CB9E51F.html) | [Session Persistence](https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/administration/GUID-8B5C8D64-2B69-4C95-86A5-C5396CB9E51F.html) | +| Azure Application Gateway for Containers | [Session Affinity](https://learn.microsoft.com/en-us/azure/application-gateway/for-containers/session-affinity?tabs=session-affinity-gateway-api) | N/A | +| Cilium | N/A | [Session Affinity](https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/#session-affinity) | +| Contour | [Session Affinity / Sticky Sessions](https://projectcontour.io/docs/1.24/config/request-routing/#session-affinity) | N/A | +| Envoy | [Session Stickiness / Stateful Sessions](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/stateful_session_filter) (Strong) | [Session Stickiness / Stateful Sessions](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/stateful_session_filter) (Weak) | +| Emissary-Ingress (Ambassador API Gateway) | [Sticky Sessions / Session Affinity](https://www.getambassador.io/docs/emissary/latest/topics/running/load-balancer#cookie) | [Sticky Sessions / Session Affinity](https://www.getambassador.io/docs/emissary/latest/topics/running/load-balancer#cookie) | +| Gloo Gateway 2.0 | [Session Affinity / Sticky Sessions](https://docs.solo.io/gloo-edge/latest/installation/advanced_configuration/session_affinity/) | [Session Affinity / Sticky Sessions](https://docs.solo.io/gloo-edge/latest/installation/advanced_configuration/session_affinity/) | +| Google Kubernetes Engine | [Session Affinity](https://cloud.google.com/load-balancing/docs/backend-service#session_affinity) | [Session Affinity](https://cloud.google.com/load-balancing/docs/backend-service#session_affinity) | +| HAProxy Ingress | [Affinity](https://haproxy-ingress.github.io/docs/configuration/keys/#affinity) | N/A | +| HAProxy Kubernetes Ingress Controller | [Session Persistence](https://www.haproxy.com/documentation/haproxy-runtime-api/reference/enable-dynamic-cookie-backend/#sidebar) | N/A | +| Istio | [Strong Session Affinity](https://istio.io/latest/docs/reference/config/networking/destination-rule/#LoadBalancerSettings-ConsistentHashLB) | [Soft Session Affinity](https://istio.io/latest/docs/reference/config/networking/destination-rule/#LoadBalancerSettings-ConsistentHashLB) | +| Kong | [Persistent Session](https://docs.konghq.com/hub/kong-inc/saml/configuration/#config-session_remember) | N/A | +| Nginx (Proxy) | [Session Persistence](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#enabling-session-persistence) | [Session Persistence](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#enabling-session-persistence) | +| Traefik | [Sticky Sessions](https://doc.traefik.io/traefik/routing/services/#sticky-sessions) | N/A | + +Visualizing the result for what implementations call "Strong Session Affinity" (aka Session Persistence), it's mostly +inconclusive: + +```mermaid +pie title What Implementations Call "Strong Session Affinity"? + "Session Affinity" : 5 + "Sticky Sessions" : 5 + "Session Persistence" : 3 + "Persistent Session": 1 + "Strong Session Affinity": 1 + "Affinity": 1 + "Session Stickiness": 1 + "Stateful Sessions": 1 +``` + +This GEP chooses to use "session persistence" as the preferred definition of strong session affinity (guaranteed) while +reserving "session affinity" to mean weak session affinity (best-effort). We selected these names because "session +persistence" and "session affinity" share a symmetry that indicates to users that there is a relationship between them. +The term "Persistence" implies a sense of strong consistency or recurring behavior, whereas "Affinity" carries a weaker +connotation related to liking or attraction. + +**Note**: One concern for using the name "session persistence" is that it may be confused the idea of persisting a +session to storage. This confusion is particularly common among Java developers, as Java defines session persistence as +storing a session to disk. + +### Defining Session Persistence + +Session persistence is when a client request is directed to the same backend server for the duration of a "session". It is achieved when a client directly provides information, such as a header, that a proxy uses as a reference to direct traffic to a specific server. Persistence is an exception to load balancing: a persistent client request bypasses the proxy's load balancing algorithm, going directly to a backend server it has previously established a session with. + +Session persistence enables more efficient application workflows: + +1. Better performance: Maintaining a single session allows a server to cache information about a client locally reducing the need for servers to exchange session data and overall storage needs. +2. Seamless client experience: Clients can reconnect to the same server without re-authenticating or re-entering their information. + +Some of the concerns of session persistence are the duration and expiration of the session, security of the transaction stream, and storage of the context or state. + +Session affinity, not to be confused with session persistence, uses an existing attribute of the request to consistently send to the same backend. Session affinity can be considered a weaker form of session persistence: it is not guaranteed to persist a connection to the same backend server if certain attributes of the request or the backends are changed. + +### Security and Privacy Implications + +Session persistence can introduce security and privacy vulnerabilities if not properly implemented. These vulnerabilities can include: + +1. Session hijacking: Attackers intercepting or predicting a valid session token to gain unauthorized access. +2. Session fixation: Attackers setting a client's session ID to a known value, which they can then use to hijack the session. +3. Session replay attacks: Attackers capturing and resending a client's message with a valid session ID. +4. Data leakage: Attackers can exploit sensitive session information cached on servers if not properly secured. +5. Denial of service attacks: Attackers can use up server resources by creating and maintaining large numbers of sessions. + +To mitigate these security concerns, it is important to implement session persistence using secure practices, such as using strong session ID generation algorithms, implementing session timeouts, encrypting sensitive data, and monitoring server resources for unusual activity. + +IP address reuse may also be a security or privacy concern when using session persistence or session affinity. If Kubernetes reuses an IP address of previously shutdown pod, the new pod may receive session persistent traffic meant for the old pod. + +Session affinity introduces fewer security and privacy vulnerabilities since there are no session tokens to protect or exploit. + +### Achieving Session Persistence + +Session persistence is achieved using attributes residing in the application layer. The following are mechanisms for achieving session persistence: + +**1. Cookie-Based Session Persistence** + +The most common mechanism is by using cookies (described by [RFC6265](https://www.rfc-editor.org/rfc/rfc6265)) with the set-cookie HTTP response header. A client will use the provided value in the set-cookie response header in a cookie request header in subsequent requests. Proxies can use this cookie header to maintain a persistent connection to a single backend server on behalf of the client. + +**2. Header-Based Session Persistence** + +Header-based stateful sessions are achieved by a backend or gateway providing an HTTP response header and the client using the same header in subsequent HTTP requests. Proxies can use this header to maintain a persistent connection to a single backend server on behalf of the client. + +**3. URL-Encoded Session Persistence** + +Session information can be also encoded into the request URL to establish a persistent session. The server rewrites the client's URL to encode the new session information automatically. The server or the gateway then decodes the session information from the URL to identify the session. + +### Session Persistence Initiation + +For all implementations of session persistence, the initiation of the persistent session is possible from various +sources, including the gateway, intermediary gateway, backend, a sidecar in a backend, or any other infrastructure +component. + +Let's consider a simple implementation comprised of gateways and backends. The following rules apply based on who initiates the session: + +- If the gateway initiates the session, the backend will be presented with session attributes regardless if it enabled them. +- If the backend initiates the session, the gateway should allow this and not force persistent connections, unless + specifically configured to. The gateway may decode and alter the cookie established by the backend to achieve + session persistence. + +It's important to note that we can have more complex implementations which involve traversing global load balancers, +regional load balancers, intermediary internal gateways, sidecars, or waypoints before reaching the backend. At any +point within this architecture, a persistent session can be initiated. See [Global Load Balancer Initiated Session Example](#global-load-balancer-initiated-session-example) +for an example of one of these alternative implementations. + +In the next sections, we will take a closer look at the initiation of sessions in both the gateway and the backend. +Please note that in the next sections, we are examining the various scenarios in which a session can be initiated. We +are not prescribing specific implementations for session persistence. The intention is to understand the possibilities +and behaviors related to session initiation while the [API](#api) section will provide more details on specific +implementation details. + +#### Gateway Initiated Session Example + +To illustrate how a gateway can initiate a session, let's examine an implementation that uses cookies for persistence. +This represents the most straightforward scenario for utilizing cookies. When a request is made, the gateway includes +the `set-cookie` header in the final response, prompting the client to store the cookie. This cookie is subsequently +used in future requests, allowing the gateway to consistently choose the same upstream, establishing a persistent +session. + +Here an example implementation of a gateway initiating a session through cookies: +```mermaid +sequenceDiagram + actor C as Client + participant G as Gateway + participant B as Backend + C->>+G: Request Web Page + activate G + G->>+B: Request + B-->>-G: Response + G->>G: Add set-cookie header + G-->>-C: Response
[set-cookie] + Note right of G: [set-cookie] indicates a response
with a set-cookie header.
May include other set-cookie
headers from backend. + C->>C: Create Cookie(s)
from set-cookie header(s) + Note right of C: [cookie] indicates a request
with one or more cookies + C->>+G: Request Web Page
[cookie] + G->>G: Consistent lookup of
server using cookie value + G->>+B: Request
[cookie] + B-->>-G: Response + G-->>-C: Response +``` + +#### Backend Initiated Session Example + +**Important**: While we took it into consideration, this GEP does not support configuring backend-initiated sessions. +This could potentially affect frameworks that initiate sessions in the backend. Implementing this feature is complicated +and requires careful design, making it suitable for exploration in a separate GEP. + +Continuing with the cookie example, when dealing with backend-initiated sessions, the process becomes somewhat more +complex. For cookie-based session persistence, the gateway needs to store a value within a cookie containing a backend +identifier. This identifier can be then used as a reference to maintain a persistent session to a specific backend. +There are several approaches a gateway could use in this situation to achieve session persistence: + +1. Insert an additional cookie +2. Modify the existing cookie's value +3. Prefix the existing cookie + +Additionally, there are variations to each of these approaches, such as making new or updated cookies transparent to the +backend, either by remove an inserted cookie or reversing modifications of the cookie's value. + +Alternatively, if the backend is not configured for session persistence, the gateway should refrain from modifying or +inserting a cookie. In this situation, the gateway should remain passive and simply forward the `set-cookie` header as +it is. + +Refer to the [Session Initiation Guidelines](#session-initiation-guidelines) section of the API for implementation +guidance. + +Here's an example implementation of a backend initiating a session and the gateway modifies the cookie's value: +```mermaid +sequenceDiagram + actor C as Client + participant G as Gateway + participant B as Backend + C->>+G: Request Web Page + activate G + G->>+B: Request + B->>B: Add set-cookie
header + B-->>-G: Response
[set-cookie] + G->>G: Modify set-cookie
header per configuration + G-->>-C: Response
[set-cookie*] + Note right of G: [set-cookie] indicates a response
with a set-cookie header
[set-cookie*] indicates a response
with a MODIFIED set-cookie header + C->>C: Create Cookie
from set-cookie header + Note right of C: [cookie] indicates a request
or response with a cookie + C->>+G: Request Web Page
[cookie] + G->>G: Consistent lookup
of server using cookie value + G->>+B: Request
[cookie] + B-->>-G: Response + G-->>-C: Response +``` + +#### Global Load Balancer Initiated Session Example + +In a more complex architecture example, a global load balancer may need to use cookies in order to maintain persistent +connections to a regional load balancer. The regional cluster load balancer initiates the session by issuing the +`set-cookie` header and subsequently uses the cookie to maintain persistent connections to a specific backend. The +global load balancer then adds or modifies a cookie in order to establish persistent connection to a regional cluster +load balancer. + +Here an example implementation of a global load balancer and a regional load balancer creating sessions through cookies: +```mermaid +sequenceDiagram + actor C as Client + participant G as Global
Load Balancer + participant R as Regional Cluster
Load Balancer + participant B as Backend + C->>+G: Request Web Page + G->>+R: Request + R->>+B: Request + B-->>-R: Response + R->>R: Initiates session by
adding set-cookie header + R-->>-G: Response
[set-cookie] + G->>G: Add or modify
set-cookie header + G-->>-C: Response
[set-cookie*] + Note right of G: [set-cookie] indicates a response
with a set-cookie header
[set-cookie*] indicates a response with a
modified or additional set-cookie header + C->>C: Create Cookie
from set-cookie header + Note right of C: [cookie] indicates a request
with one or more cookies + C->>+G: Request Web Page
[cookie] + G->>G: Consistent lookup of
regional cluster load balancer
using cookie value + G->>+R: Request
[cookie] + R->>R: Consistent lookup of backend
using cookie value + R->>+B: Request
[cookie] + B-->>-R: Response + R-->>-G: Response + G-->>-C: Response +``` + +### When does an application require session persistence? + +Enabling session persistence is a required configuration for applications intentionally designed by the application +developer to use it, as they will encounter failures or malfunctions when it's not enabled. However, it's worth noting +that certain applications may be designed to function both with and without session persistence. Regardless, the +importance of Gateway API supporting session persistence remains emphasized because it is frequently seen as a necessary +feature. + +Conversely, apps that have not been designed or tested with session persistence in mind may misbehave when it is +enabled, primarily because of the impacts of load distribution on the app. Apps using session persistence must account +for aspects like load shedding, draining, and session migration as a part of their application design. + +### The Relationship of Session Persistence and Session Affinity + +As discussed in [Naming](#naming), we defined session persistence as "strong" and session affinity as "weak". Though +this GEP's intention is not to define an API for session affinity, let's understand its distinction with session +persistence. + +While session persistence uses attributes in the application layer, session affinity can also use attributes below the +application layer. Session affinity doesn't require a specific backend identifier to be encoded in a cookie or header; +instead, it can use any existing connection attributes to establish a consistent hashing load balancing algorithm. This +implies session affinity can use cookies or headers, as seen in Istio's [ConsistentHashLB](https://istio.io/latest/docs/reference/config/networking/destination-rule/#LoadBalancerSettings-ConsistentHashLB). With session +affinity, the cookie or header will be hashed on its arbitrary value. + +It is important to note the session affinity is less reliable and doesn't guarantee persistent connections to the same +backend server. If a proxy or load balancer restarts, or if backends are added to the backend pool, the session affinity +mechanism will likely redirect the user's connection to a new backend. In contrast, session persistence encodes a +backend identifier in a cookie or header, so as long as the backend still exists, it will be unaffected by proxy +restarts or changes in the backend pool. + +Session affinity can be achieved by deterministic load balancing algorithms or a proxy feature that tracks IP-to-backend +associations such as [HAProxy's stick tables](https://www.haproxy.com/blog/introduction-to-haproxy-stick-tables/) or +[Cilium's session affinity](https://docs.cilium.io/en/v1.12/gettingstarted/kubeproxy-free/#id2). + +We can also examine how session persistence and session affinity functionally work together, by framing the relationship +into a two tiered logical decision made by the data plane: + +1. If the request contains a session persistence identity (e.g. in a cookie or header), then route it directly to the + backend it has previously established a session with. +2. If no session persistence identity is present, load balance as per load balancing configuration, taking into account + the session affinity configuration (e.g. by utilizing a hashing algorithm that is deterministic). + +This tiered decision-based logic is consistent with the idea that session persistence is an exception to load balancing. +Though there are different ways to frame this relationship, this design will influence the separation between +persistence and affinity API design. + +### Implementations + +In this section, we will describe how implementations achieve session persistence, along with a breakdown of related configuration options. Input from implementations is appreciated to complete this information. + +In the following tables, we will example two types of APIs: + +1. Dataplane APIs +2. Implementation APIs + +Generally, the implementation API programs the dataplane API; however these two are not always clearly separated. The two types of APIs can use different API structures for configuring the same feature. Examining the dataplane APIs helps to remove the layer of API abstraction that implementations provide. Removing this layer avoids situations where implementations don’t fully implement all capabilities of a dataplane API or obfuscate certain configuration around session persistence. On the other hand, examining implementation APIs provides valuable data points in what implementations are interested in configuring. + +**Table Last Updated:** Feb 21, 2024 + +| **Technology** | **Technology Type** | **Session Persistence Type** | **Configuration Options** | **Configuration Association (Global, Gateway, Route, or Backends)** | **Notes** | +|--- |--- |--- |--- |--- |--- | +| Acnodal EPIC | Implementation (Envoy) | N/A | Supports Gateway API Only* | N/A | *Acnodal Epic solely uses Gateway API; therefore, it doesn’t yet have a way to configure session persistence. [Acnodal EPIC Docs](https://www.epick8sgw.io/docs/) | +| Amazon Elastic Kubernetes Service | Implementation / Dataplane | N/A | Supports Gateway API Only* | N/A | *Amazon Elastic Kubernetes Service solely uses Gateway API; therefore, it doesn’t yet have a way to configure session persistence. [Amazon Elastic Kubernetes Service Docs](https://www.gateway-api-controller.eks.aws.dev/) | +| Apache APISIX | Implementation (Nginx) | [Cookie-Based](https://apisix.apache.org/docs/apisix/admin-api/#upstream) | hash_on=[vars \| header \| cookie \| consumer]
key=cookie_name | [Upstream](https://apisix.apache.org/docs/apisix/admin-api/#upstream) (Route or Backends) | N/A | +| | Implementation (Nginx) | [Header-Based](https://apisix.apache.org/docs/apisix/terminology/upstream/#header) | hash_on=[vars \| header \| cookie \| consumer]
key=header_name | [Upstream](https://apisix.apache.org/docs/apisix/admin-api/#upstream) (Route or Backends) | N/A | +| Apache httpd | Web Server | [Cookie-Based / URL-Encoded](https://httpd.apache.org/docs/2.4/mod/mod_proxy_balancer.html) | Cookie Attributes | N/A | N/A | +| Avi Kubernetes Operator | Implementation / Dataplane | [Cookie-Based](https://docs.vmware.com/en/VMware-NSX-T-Data-Center/3.2/administration/GUID-8B5C8D64-2B69-4C95-86A5-C5396CB9E51F.html) | Shared Persistence Cookie Mode=[Insert \| Prefix \| Rewrite] Cookie Name=name Cookie Domain=domain Cookie Fallback=domain Cookie Path=path Cookie Garbling Cookie Type=[ Session Cookie \| Persistence Cookie] Http Only Flag Secure Flag Max Idle Time=time Max Cookie Age=time | [Route](https://docs.vmware.com/en/VMware-NSX-Advanced-Load-Balancer/1.11/Avi-Kubernetes-Operator-Guide/GUID-E8F3C338-46FB-412E-8B46-16EE2C12A8AF.html) | N/A | +| Azure Application Gateway for Containers | Implementation / Dataplane | [Cookie-Based](https://learn.microsoft.com/en-us/azure/application-gateway/for-containers/session-affinity?tabs=session-affinity-gateway-api) | affinityType=[application-cookie \| managed-cookie]
cookieName=name
cookieDuration=seconds | [Route](https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/application-gateway/for-containers/api-specification-kubernetes.md#alb.networking.azure.io/v1.RoutePolicy) | RoutePolicy which attaches to HTTPRoutes | +| BIG-IP Kubernetes Gateway | Implementation (F5 BIG-IP) | N/A | Supports Gateway API Only* | N/A | *BIG-IP Kubernetes Gateway solely uses Gateway API; therefore, it doesn’t yet have a way to configure session persistence. [BIG-IP Kubernetes Gateway Docs](https://gateway-api.f5se.io/) | +| Cilium | Implementation / Dataplane | None | None | None | Cilium has no documented way of doing session persistence. [Cilium Docs](https://cilium.io/) | +| Contour | Implementation (Envoy) | [Cookie-Based](https://projectcontour.io/docs/1.24/config/api/#projectcontour.io/v1.CookieRewritePolicy) | Name=name
pathRewrite=path
domainRewrite=domain
secure
sameSite | [Route](https://projectcontour.io/docs/1.24/config/api/#projectcontour.io/v1.Route) and [Service](https://projectcontour.io/docs/1.24/config/api/#projectcontour.io/v1.Service) (Backends) | Envoy does not natively support cookie attribute rewriting nor adding attributes other than path and TTL, but rewriting and adding additional attributes is possible via Lua ([Contour design reference](https://github.com/projectcontour/contour/blob/main/design/cookie-rewrite-design.md), [Envoy Issue](https://github.com/envoyproxy/envoy/issues/15612)). | +| Easegress | Implementation / Dataplane | None | None | None | [Easegress Docs](https://megaease.com/docs/easegress/) | +| Emissary-Ingress | Implementation (Envoy) | [Cookie-Based](https://www.getambassador.io/docs/emissary/latest/topics/running/load-balancer#cookie) | Name=name
Path=path
TTL=duration | [Module or Mapping](https://www.getambassador.io/docs/emissary/latest/topics/running/load-balancer#cookie) (Global or Route) | N/A | +| | | [Header-Based](https://www.getambassador.io/docs/emissary/latest/topics/running/load-balancer#header) | Name=name | [Module or Mapping](https://www.getambassador.io/docs/emissary/latest/topics/running/load-balancer#cookie) (Global or Route) | N/A | +| Envoy | Dataplane | [Cookie-Based](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/http/stateful_session/cookie/v3/cookie.proto) | Name=name
Path=path
TTL=duration | [HttpConnectionManager](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto) (Route) | Envoy does not natively support cookie attribute rewriting nor adding attributes other than path and TTL, but rewriting and adding additional attributes is possible via Lua ([Contour design reference](https://github.com/projectcontour/contour/blob/main/design/cookie-rewrite-design.md), [Envoy Issue](https://github.com/envoyproxy/envoy/issues/15612)). | +| | | [Header-Based](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/http/stateful_session/header/v3/header.proto) | Name=name | [HttpConnectionManager](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/http_connection_manager/v3/http_connection_manager.proto) (Route) | N/A | +| Envoy Gateway | Implementation (Envoy) | N/A | Supports Gateway API Only* | N/A | *Envoy Gateway solely uses Gateway API; therefore, it doesn’t yet have a way to configure session persistence. [Envoy Gateway Docs](https://gateway.envoyproxy.io/v0.3.0/index.html) | +| Flomesh Service Mesh | Implementation / Dataplane (Pipy) | ? | ? | ? | ? | +| Gloo Gateway | Implementation (Envoy) | [Cookie-Based](https://docs.solo.io/gloo-edge/latest/reference/api/envoy/api/v2/route/route.proto.sk/#cookie) | Name=name Path=path TTL=duration | [Route](https://docs.solo.io/gloo-edge/latest/reference/api/envoy/api/v2/route/route.proto.sk/#route) (Route) | N/A | +| | | [Header-Based](https://docs.solo.io/gloo-edge/latest/reference/api/envoy/api/v2/route/route.proto.sk/#hashpolicy) | Name=name | [Route](https://docs.solo.io/gloo-edge/latest/reference/api/envoy/api/v2/route/route.proto.sk/#route) (Route) | N/A | +| Google CloudRun | Dataplane | [Cookie-Based](https://cloud.google.com/run/docs/configuring/session-affinity) | Enabled / Disabled | [Service](https://cloud.google.com/run/docs/configuring/session-affinity) (Backends) | Only allowed to turn off or on, no other configuration items | +| Google Kubernetes Engine | Implementation / Dataplane | [Cookie-Based](https://cloud.google.com/load-balancing/docs/backend-service#session_affinity) | GENERATED_COOKIE or HTTP_COOKIE=name
cookieTtlSec | [Backend Policy](https://cloud.google.com/kubernetes-engine/docs/how-to/configure-gateway-resources#session_affinity) (Backends) | Google Kubernetes Engine [lists](https://cloud.google.com/load-balancing/docs/backend-service#bs-session-affinity) the products that can do persistence/affinity mode. All persistence/affinity options are exclusive and can’t be used at the same time.
Note: Google Kubernetes Engine defines everything (persistence and affinity) as session affinity. | +| | | [Header-Based](https://cloud.google.com/load-balancing/docs/backend-service#header_field_affinity) | httpHeaderName=name | [Backend Policy](https://cloud.google.com/kubernetes-engine/docs/how-to/configure-gateway-resources#session_affinity) (Backends) | N/A | +| HAProxy | Dataplane | [Cookie-Based](https://docs.haproxy.org/2.6/configuration.html#4.2-cookie) | name=name
[rewrite \| insert \| prefix ]
indirect
nocache
postonly
preserve
httponly
secure
domain=domain
maxidle=idle
maxlife=life
dynamic
attr=value | [Default or Backends](https://docs.haproxy.org/2.6/configuration.html#4.2-cookie) (Global or Backends) | HAProxy allows for operational cookie strategy configuration (i.e. when/how HAProxy should inject cookies) | +| HAProxy Ingress | Implementation (HAProxy) | [Cookie-Based](https://haproxy-ingress.github.io/docs/configuration/keys/#affinity) | affinity (enable/disable)
cookie-key=key
session-cookie-domain=domain
session-cookie-dynamic=[true \| false]
session-cookie-keywords=keywords
session-cookie-name=name
session-cookie-preserve=[true \| false]
session-cookie-same-site=[true \| false]
session-cookie-shared=[true \| false]
session-cookie-strategy=strategy
session-cookie-value-strategy=value_strategy | [Backend](https://haproxy-ingress.github.io/docs/configuration/keys/#affinity) (Backends) | N/A | +| Hashicorp Consul | Implementation (Envoy) | N/A | Supports Gateway API Only* | N/A | *Hashicorp Consul solely uses Gateway API; therefore, it doesn’t yet have a way to configure session persistence. [Hashicorp Consul API Gateway Docs](https://developer.hashicorp.com/consul/docs/api-gateway) | +| Istio | Implementation (Envoy) | [Cookie-Based](https://istio.io/latest/docs/reference/config/networking/destination-rule/#LoadBalancerSettings-ConsistentHashLB-HTTPCookie) | Name=name
Path=path
TTL=duration | [ConsistentHashLB](https://istio.io/latest/docs/reference/config/networking/destination-rule/#LoadBalancerSettings-ConsistentHashLB) (Backends) | Istio also supports turning on cookie-based session persistence via the Pilot ENV variable [PILOT_PERSISTENT_SESSION_LABEL](https://istio.io/latest/docs/reference/commands/pilot-discovery/#envvars). | +| | Implementation (Envoy) | [Header-Based](https://istio.io/latest/docs/reference/config/networking/destination-rule/#LoadBalancerSettings-ConsistentHashLB) | Name=name | [ConsistentHashLB](https://istio.io/latest/docs/reference/config/networking/destination-rule/#LoadBalancerSettings-ConsistentHashLB) (Backends) | N/A | +| Java Servlet | Web Server | [Cookie-Based / URL-Encoded](https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html) | invalidate()
setAttribute(String name, Object value)
setMaxInactiveInterval(int interval) | N/A | Java Servlets do not natively support proxy functions. | +| Kong | Implementation / Dataplane | [Cookie-Based](https://docs.konghq.com/hub/kong-inc/session/) | cookie_name=name
rolling_timeout=timeout
absolute_timeout=timeout
idling_timeout=timeout
cookie_path=path
cookie_domain=domain
cookie_same_site=[Strict \| Lax \| None \| off]
cookie_http_only
cookie_secure=[true \| false]
stale_ttl=duration
cookie_persistent=[true \| false]
storage=storage_type | [Route, Service, Global](https://docs.konghq.com/hub/kong-inc/session/) (Route or Backends or Global) | N/A | +| | | [Header-Based](https://docs.konghq.com/gateway/latest/how-kong-works/load-balancing/#balancing-algorithms) | name | [Upstreams](https://docs.konghq.com/gateway/3.2.x/admin-api/#add-upstream) (Backends) | N/A | +| Kuma | Implementation (Envoy) | None | None | None | Kuma has no documentation on how it supports session persistence or cookies. [Kuma Docs](https://kuma.io/docs/2.1.x/) | +| Linkerd | Gamma Implementation | None | None | None | [Linkerd Docs](https://linkerd.io/) | +| LiteSpeed Ingress Controller | ? | ? | ? | ? | ? | +| Nginx | Dataplane | [Cookie-Based (Nginx Plus Only)](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#enabling-session-persistence) | Name=name
Expires=time
Domain=domain
HttpOnly
SameSite = [strict \| lax \| none \| $variable]
Secure
path=path | [Upstream](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#enabling-session-persistence) (Backends) | See also [Sticky Cookie](https://nginx.org/en/docs/http/ngx_http_upstream_module.html?&_ga=2.184452070.1306763907.1680031702-1761609832.1671225057#sticky_cookie) | +| NGINX Gateway Fabric | Implementation (Nginx) | N/A | Supports Gateway API Only* | N/A | *NGINX Gateway Fabric solely uses Gateway API; therefore, it doesn’t yet have a way to configure session persistence. [NGINX Gateway Fabric Docs](https://github.com/nginxinc/nginx-gateway-fabric) | +| STUNner | Implementation / Dataplane | None | None | None | [STUNner Docs](https://github.com/l7mp/stunner) | +| Traefik | Implementation / Dataplane | [Cookie-Based](https://doc.traefik.io/traefik/routing/services/#sticky-sessions) | name=name
secure
httpOnly
sameSite=[none \| lax \| strict ] | [Services](https://doc.traefik.io/traefik/routing/services/#sticky-sessions) (Backends) | N/A | +| Tyk | Implementation / Dataplane | None | None | None | [Tyk Docs](https://tyk.io/docs/) | +| WSO2 APK | Implementation / Dataplane | None | None | None | [WSO2 APK Docs](https://apk.docs.wso2.com/en/latest/) | + +### Sessions in Java + +Java application servers such as Tomcat and Jetty, were the first to standardize the API around cookies and sessions. +These Java applications introduced the “jsessionid” cookie and session IDs encoded in URL parameters as well as more +advanced features such as session migration, replication, and on demand session activation. It’s important for Gateway +API to examine cookie use cases and history from Java APIs to ensure the API is designed appropriately. + +### Session Affinity in K8S Services + +Kubernetes provides an API that allows you to enable [session affinity](https://kubernetes.io/docs/reference/networking/virtual-ips/#session-affinity) +on service objects. It ensures consistent sessions by utilizing the client's IP address and also offers the option to +set a timeout for the maximum session duration. Implementations of Gateway API, such as service mesh use cases, may use +the service IP directly. In these cases where both Kubernetes service session affinity and Gateway API session +persistence are both enabled, the route MUST be rejected, and a status should be set describing the incompatibility of +these two configurations. + +## API + +In this section, we will explore the questions and design elements associated with a session persistence API. + +We will present two distinct patterns for configuring session persistence: + +1. `BackendLBPolicy`: a Direct Policy Attachment for backends (Services, ServiceImports, or any + implementation-specific backendRef) +2. An inline API update to HTTPRoute and GRPCRoute rules + +### BackendLBPolicy API + +In order to apply session persistence configuration to a backend, we will implement it as a [Policy Attachment](../../reference/policy-attachment.md). +The new metaresource is named `BackendLBPolicy` and is responsible for configuring load balancing-related configuration +for traffic intended for a backend after routing has occurred. It is defined as a [Direct Policy Attachment](../gep-713/index.md#direct-policy-attachment) +without defaults or overrides, applied to the targeted backend. + +Instead of utilizing a specific, session persistence-only policy object, we introduce a more generic API object named +`BackendLBPolicy`. This design provides tighter coupling with other load balancing configuration which helps reduce +CRD proliferation. For instance, `BackendLBPolicy` could be augmented to add configuration for selecting a load +balancing algorithm for traffic to the backends, as desired in issue [#1778](https://github.com/kubernetes-sigs/gateway-api/issues/1778). +`BackendLBPolicy` could also be later expanded to contain [session affinity](#the-relationship-of-session-persistence-and-session-affinity) +configuration. This would provide a convenient grouping of the two related APIs within the same policy object. +Additionally, other future enhancements to the API may include the addition of timeouts, connection draining, and +logging within `BackendLBPolicy`. + +As for achieving session persistence, this API currently exposes the `Type` field which allows selection between +cookie-based and header-based session persistence. Cookie-based session persistence is considered a core feature, +while header-based session persistence is extended and therefore optional. + +```go +// BackendLBPolicy provides a way to define load balancing rules +// for a backend. +type BackendLBPolicy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of BackendLBPolicy. + Spec BackendLBPolicySpec `json:"spec"` + + // Status defines the current state of BackendLBPolicy. + Status PolicyStatus `json:"status,omitempty"` +} + +// BackendLBPolicySpec defines the desired state of +// BackendLBPolicy. +// Note: there is no Override or Default policy configuration. +type BackendLBPolicySpec struct { + // TargetRef identifies an API object to apply policy to. + // Currently, Backends (i.e. Service, ServiceImport, or any + // implementation-specific backendRef) are the only valid API + // target references. + // +listType=map + // +listMapKey=group + // +listMapKey=kind + // +listMapKey=name + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=16 + TargetRefs []LocalPolicyTargetReference `json:"targetRefs"` + + // SessionPersistence defines and configures session persistence + // for the backend. + // + // Support: Extended + // + // +optional + SessionPersistence *SessionPersistence `json:"sessionPersistence"` +} + +// SessionPersistence defines the desired state of +// SessionPersistence. +// +kubebuilder:validation:XValidation:message="AbsoluteTimeout must be specified when cookie lifetimeType is Permanent",rule="!has(self.cookieConfig) || !has(self.cookieConfig.lifetimeType) || self.cookieConfig.lifetimeType != 'Permanent' || has(self.absoluteTimeout)" +type SessionPersistence struct { + // SessionName defines the name of the persistent session token + // which may be reflected in the cookie or the header. Users + // should avoid reusing session names to prevent unintended + // consequences, such as rejection or unpredictable behavior. + // + // Support: Implementation-specific + // + // +optional + // +kubebuilder:validation:MaxLength=128 + SessionName *string `json:"sessionName,omitempty"` + + // AbsoluteTimeout defines the absolute timeout of the persistent + // session. Once the AbsoluteTimeout duration has elapsed, the + // session becomes invalid. + // + // Support: Extended + // + // +optional + AbsoluteTimeout *Duration `json:"absoluteTimeout,omitempty"` + + // IdleTimeout defines the idle timeout of the persistent session. + // Once the session has been idle for more than the specified + // IdleTimeout duration, the session becomes invalid. + // + // Support: Extended + // + // +optional + IdleTimeout *Duration `json:"idleTimeout,omitempty"` + + // Type defines the type of session persistence such as through + // the use a header or cookie. Defaults to cookie based session + // persistence. + // + // Support: Core for "Cookie" type + // + // Support: Extended for "Header" type + // + // +optional + // +kubebuilder:default=Cookie + Type *SessionPersistenceType `json:"type,omitempty"` + + // CookieConfig provides configuration settings that are specific + // to cookie-based session persistence. + // + // Support: Core + // + // +optional + CookieConfig *CookieConfig `json:"cookieConfig,omitempty"` +} + +// Duration is a string value representing a duration in time. The format is as specified +// in GEP-2257, a strict subset of the syntax parsed by Golang time.ParseDuration. +// +// +kubebuilder:validation:Pattern=`^([0-9]{1,5}(h|m|s|ms)){1,4}$` +type Duration string + +// +kubebuilder:validation:Enum=Cookie;Header +type SessionPersistenceType string + +const ( + // CookieBasedSessionPersistence specifies cookie-based session + // persistence. + // + // Support: Core + CookieBasedSessionPersistence SessionPersistenceType = "Cookie" + + // HeaderBasedSessionPersistence specifies header-based session + // persistence. + // + // Support: Extended + HeaderBasedSessionPersistence SessionPersistenceType = "Header" +) + +// CookieConfig defines the configuration for cookie-based session persistence. +type CookieConfig struct { + // LifetimeType specifies whether the cookie has a permanent or + // session-based lifetime. A permanent cookie persists until its + // specified expiry time, defined by the Expires or Max-Age cookie + // attributes, while a session cookie is deleted when the current + // session ends. + // + // When set to "Permanent", AbsoluteTimeout indicates the + // cookie's lifetime via the Expires or Max-Age cookie attributes + // and is required. + // + // When set to "Session", AbsoluteTimeout indicates the + // absolute lifetime of the cookie tracked by the gateway and + // is optional. + // + // Support: Core for "Session" type + // + // Support: Extended for "Permanent" type + // + // +optional + // +kubebuilder:default=Session + LifetimeType *CookieLifetimeType `json:"lifetimeType,omitempty"` +} + +// +kubebuilder:validation:Enum=Permanent;Session +type CookieLifetimeType string + +const ( + // SessionCookieLifetimeType specifies the type for a session + // cookie. + // + // Support: Core + SessionCookieLifetimeType CookieLifetimeType = "Session" + + // PermanentCookieLifetimeType specifies the type for a permanent + // cookie. + // + // Support: Extended + PermanentCookieLifetimeType CookieLifetimeType = "Permanent" +) +``` + +### Route Rule API + +To support route rule level configuration, this GEP also introduces an API as inline fields within HTTPRouteRule and GRPCRouteRule. +Any configuration that is specified at Route Rule level MUST override configuration that is attached at the backend level because route rule have a more global view and responsibility for the overall traffic routing. +This route rule level API for enabling session persistence currently uses the same `SessionPersistence` struct from the +`BackendLBPolicy` API. + +```go +type HTTPRouteRule struct { + [...] + + // SessionPersistence defines and configures session persistence + // for the route rule. + // + // Support: Extended + // + // +optional + SessionPersistence *SessionPersistence `json:"sessionPersistence"` +} +``` + +```go +type GRPCRouteRule struct { + [...] + + // SessionPersistence defines and configures session persistence + // for the route rule. + // + // Support: Extended + // + // +optional + SessionPersistence *SessionPersistence `json:"sessionPersistence"` +} +``` + +### API Granularity + +The purpose of this session persistence API spec is to enable developers to specify that a specific backend expects a +persistent session. However, it intentionally avoids specifying low-level details or configurations related to the +session persistence implementation, such as cookie attributes. This decision is because the Gateway API supports various +infrastructure types, and some implementations that already provide session persistence may not be able to adhere to a +low-level API. + +For instance, platforms using global load balancers to maintain persistent sessions between regional load balancers, or +Tomcat servlets generating distinct cookies per server. In such scenarios, it is important that this GEP does not +obstruct the existing use of cookies while enabling session persistence. Enabling particular low-level API +configurations, like allowing customization of the cookie name, could prevent certain implementations from conforming to +the spec. In other words, opting for a higher-level API provides better interoperability among our implementations. + +However, this API spec does allow specifying specific forms or types of session persistence through the `Type` field in +the `SessionPersistence` struct, including options for cookie-based or header-based session persistence. This API field +accommodates implementations that offer multiple methods of session persistence, while also allowing users to specify +their preferred form of session persistence if desired. + +### Target Persona + +Referring to the [Gateway API Security Model](../../concepts/security-model.md#roles-and-personas), +the target kubernetes role/persona for session persistence are application developers, as mentioned in the [When does an application require session persistence?](#when-does-an-application-require-session-persistence) +section. It is the responsibility of the application developers to adjust the persistence configuration to ensure the +functionality of their applications. + +### Prior Art + +Referring to our [Implementations](#Implementations) table on session persistence, the majority of Gateway API +implementations designed session persistence in their APIs to be attached to a service or backends. This should be +considered cautiously, as making associations to Gateway API's notion of Gateway, Route, and Service to other +implementation's objects is hard to directly translate. The idea of a route in Gateway API is often not the same as a +route in any given implementation. + +### API Attachment Points + +The new `BackendLBPolicy` metaresource only supports attaching to a backend. A backend can be a Service, +ServiceImport (see [GEP-1748](../gep-1748/index.md)), or any implementation-specific backends that are a valid +[`BackendObjectReference`](../../reference/spec.md#gateway.networking.k8s.io%2fv1.BackendObjectReference). Enabling session +persistence for a backend enables subsequently enables it for any route directing traffic to this backend. To learn more +about the process of attaching a policy to a backend, please refer to [GEP-713](../gep-713/index.md). + +On the other hand, configuring the `sessionPersistence` field in the route rule enables session persistence exclusively +for the traffic directed to the `backendRefs` in this route rule. This means applying session persistence configuration +to a route rule MUST NOT affect traffic for other routes or route rules. Designing the configuration for a specific +route rule section rather than the route entirely, allows users to configure session persistence in a more granular +fashion. This approach avoids the need to decompose routes if the configuration is specific to a route path. + +Session persistence configuration specified in a route rule SHALL override equivalent configuration in `BackendLBPolicy`. +In this situation, implementations MAY want to indicate a warning via a log or status. Refer to [GEP-713](../gep-713/index.md) +and/or [GEP-2648](../gep-2648/index.md) for more specific details on how to handle override scenarios. + +Edge cases will arise when implementing session persistence support for both backends and route rules through +`BackendLBPolicy` and the route rule's `sessionPersistence` field. For guidance on addressing conflicting +attachments, please consult the [Edge Case Behavior](#edge-case-behavior) section, which outlines API +use cases. Only a subset of implementations have already designed their data plane to incorporate route rule level session +persistence, making it likely that route rule level session persistence will be less widely implemented. + +### Traffic Splitting + +In scenarios involving traffic splitting, session persistence impacts load balancing done after routing. +When a persistent session is established and traffic splitting is configured across services, the persistence to a single backend MUST be maintained across services, even if the weight is set to 0. +Consequently, a persistent session takes precedence over traffic split +weights when selecting a backend after route matching. It's important to note that session persistence does not impact +the process of route matching. + +When using multiple backends in traffic splitting, all backend services should have session persistence enabled. +Nonetheless, implementations MUST carefully consider how to manage traffic splitting scenarios in which one service has +persistence enabled while the other does not. This includes scenarios where users are transitioning to or from an +implementation version designed with or without persistence. For traffic splitting scenario within a single route rule, +this GEP leaves the decision to the implementation. Implementations MUST choose to apply session persistence to all +backends equally, reject the session persistence configuration entirely, or apply session persistence only for the +backends with it configured. + +See [Edge Case Behavior](#edge-case-behavior) for more use cases on traffic splitting. + +### Cookie Attributes + +While the API is intended to be generic, as described in [API Granularity](#api-granularity), a majority of +implementations will employ session persistence through cookies. Therefore, let's explore the possibilities of cookie +configuration for these APIs. + +A cookie is composed of various attributes, each represented as key=value pairs. While some attributes may have optional +values, the cookie name attribute is the only mandatory one, and the rest are considered optional. + +The cookie attributes defined by [RFC6265](https://www.rfc-editor.org/rfc/rfc6265#section-5.2) are: + +- Name=_value_ +- Expires=_date_ +- Max-Age=_number_ +- Domain=_domain_ +- Path=_path-value_ +- Secure +- HttpOnly + +Other cookie attributes not defined by RFC6265, but are captured in draft RFCs and could be considered de facto +standards due to wide acceptance are: + +- SameSite=[Strict|Lax|None] +- Partitioned + +Unless a `sessionPersistence` API field can be satisfied through a manipulating a cookie attribute, the attributes +of the cookies are considered as opaque values in this spec and are to be determined by the individual implementations. +Let's discuss some of these cookie attributes in more detail. + +#### Name + +The `Name` cookie attribute MAY be configured via the `SessionName` field in `sessionPersistence`. However, this field +is implementation-specific because it's impossible to create a conformance test for it, given that sessions could be +created in a variety of ways. Additionally, `SessionName` is not universally supported as some implementations, such as +ones supporting global load balancers, don't have the capability to configure the cookie name. Some implementations +have a fixed cookie name, and therefore `SessionName` may be reflected in the value of the cookie. + +The use case for modifying the cookie name using `SessionName` is that certain users might need to align it with an +existing cookie name, such as Java's `JSESSIONID`. Refer to [Session Initiation Guidelines](#session-initiation-guidelines) +for details on how this GEP supports existing sessions. If `SessionName` is not specified, then a unique cookie name +should be generated. + +#### Expires / Max-Age + +The `Expires` and `Max-Age` cookie attributes are important in distinguishing between [session cookies and permanent +cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_the_lifetime_of_a_cookie). Session cookies do +not include either of these attributes, while permanent cookies will contain one of them. Session cookies can still +have an expiration or timeout, but it will be accomplished through alternative mechanisms, such as the proxy tracking +the cookie's lifetime via its value. + +The `LifetimeType` API field specifies whether a cookie should be a session or permanent cookie. Additionally, the lifetime +or timeout for both session and permanent cookies is represented by `AbsoluteTimeout`. In the case of +`LifetimeType` being `Permanent`, `AbsoluteTimeout` MUST configure the `Expires` or `Max-Age` cookie attributes. +Conversely, if `LifetimeType` is `Session`, `AbsoluteTimeout` MUST regulate the cookie's lifespan through a +different mechanism, as mentioned above. If `LifetimeType` is set to `Permanent`, then `AbsoluteTimeout` MUST +also be set as well. This requirement is necessary because an expiration value is required to set `Expires` or `Max-Age`. +`LifetimeType` of `Session` is core support level and the default, while `LifetimeType` of `Permanent` is extended. + +See [issue #2747](https://github.com/kubernetes-sigs/gateway-api/issues/2747) for more context regarding distinguishing +between permanent and session cookies. + +#### Path + +The cookie's `Path` attribute defines the URL path that must exist in order for the client to send the `cookie` header. +Whether attaching session persistence to an xRoute or a service, it's important to consider the relationship the cookie +`Path` attribute has with the route path. + +When session persistence is enabled on a xRoute rule, the implementor should interpret the path as +configured on the xRoute. To interpret the `Path` attribute from an xRoute, implementors should take note of the +following: + +1. For an xRoute that matches all paths, the `Path` should be set to `/`. +2. For an xRoute that has multiple paths, the `Path` should be interpreted based on the route path that was matched. +3. For an xRoute using a path that is a regex, the `Path` should be set to the longest non-regex prefix (.e.g. if the + path is /p1/p2/*/p3 and the request path was /p1/p2/foo/p3, then the cookie path would be /p1/p2). + +It is also important to note that this design makes persistent session unique per route path. For instance, if two +distinct routes, one with path prefix `/foo` and the other with `/bar`, both target the same service, the persistent +session won't be shared between these two paths. + +Conversely, if the `BackendLBPolicy` policy is attached to a service, the `Path` attribute MUST be left +unset. This is because multiple routes can target a single service. If the `Path` cookie attribute is configured in this +scenario, it could result in problems due to the possibility of different paths being taken for the same cookie. +Implementations MUST also handle the case where the client is a browser making requests to multiple persistent services +from the same page. + +#### Secure, HttpOnly, SameSite + +The `Secure`, `HttpOnly`, and `SameSite` cookie attributes are security-related. The API implementers SHOULD follow the +security-by-default principle and configure these attributes accordingly. This means enabling `Secure` and `HttpOnly`, +and setting `SameSite` to `Strict`. However, in certain implementation use cases such as service mesh, secure values +might not function as expected. In such cases, it's acceptable to make appropriate adjustments. + +### Session Persistence API with GAMMA + +The object of the [GAMMA (Gateway API for Mesh Management and Administration)](../../mesh/gamma.md) +initiative is to provide support for service mesh and mesh-adjacent use-cases with Gateway API. GAMMA is focused on +defining how Gateway API could also be used for inter-service or [east/west](../../concepts/glossary.md#eastwest-traffic) +traffic within the same cluster. + +Given that service meshes commonly have session persistence requirements, this API design should take into consideration +session persistence needs in GAMMA and service mesh scenarios. + +### Session Initiation Guidelines + +As illustrated in the examples provided in [Session Persistence Initiation](#session-persistence-initiation), +implementations must consider how to manage sessions initiated by other components. As mentioned in [Backend Initiated Session Example](#backend-initiated-session-example), +this GEP does not support configuring backend-initiated persistent sessions. We leave the decision of handling existing +sessions with each specific implementation. In the case of cookie-based session persistence, an implementation MAY +either rewrite the cookie or insert an additional cookie, or to do nothing (resulting in the lack of a +persistent session). In general, inserting an additional cookie is a generally safe option, but it's important for +implementations to exercise their own discretion. However, regardless of the implementation's design choice, the +implementation MUST be able to handle multiple cookies. + +### Session Persistence Failure Behavior + +In a situation where session persistence is configured and the backend becomes unhealthy, this GEP doesn't specify a +prescribed fallback behavior mechanism or HTTP status code. Implementations MAY exhibit different behaviors depending +on whether active health checking is enabled. Data planes MAY fall back to available backends, disregarding the broken +session, and reestablish session persistence when the backend becomes available again. + +### Edge Case Behavior + +Implementing session persistence is complex and involves many edge cases. In this section, we will outline API +configuration scenarios (use cases) and how implementations should handle them. + +#### Attaching Session Persistence to both Service and a Route Rule + +In a situation which: + +- `ServiceA` with `BackendLBPolicy` attached +- `RouteX` with `sessionPersistence` configured on the route rule and backend `ServiceA` + +The `sessionPersistence` configuration inline to `RouteX` route rule MUST take precedence over `BackendLBPolicy`. Since +routes direct traffic to services, the policy attached to route operates at a higher-level and MUST override policies +applied to individual services. + +```mermaid +graph TB + RouteX ----> ServiceA((ServiceA)) + BackendLBPolicyServiceA[BackendLBPolicy] -.-> ServiceA + BackendLBPolicyRouteA[SessionPersistence] -.Precedence.-> RouteX + linkStyle 2 stroke:red; +``` + +#### Two Routes Rules have Session Persistence to the Same Service + +Consider the situation in which two different route paths have session persistence configured and are going to the same +service: + +```yaml +kind: HTTPRoute +metadata: + name: routeX +spec: + rules: + - matches: + - path: + value: /a + backendRefs: + - name: servicev1 + sessionPersistence: + name: session-a + - matches: + - path: + value: /b + backendRefs: + - name: servicev1 + weight: 0 + - name: servicev2 + weight: 100 + sessionPersistence: + name: session-b +``` + +Route rules referencing the same service MUST NOT share persistent sessions (i.e. the same cookie). Let's illustrate +this by the following commands: + +1. Curl to `/a` which establishes a persistent session with `servicev1` +2. Curl to `/b` routes MUST direct traffic to `servicev2` since the persistent session established earlier is not + shared with this route path. + +#### Route Rules Referencing to a Session Persistent Enabled Service Must Not Share Sessions + +Consider the situation in which two different route paths are going to the same service, and session persistence is enabled with the service via `BackendLBPolicy`: + +```yaml +kind: HTTPRoute +metadata: + name: routeX +spec: + rules: + - matches: + - path: + value: /a + backendRefs: + - name: servicev1 + - matches: + - path: + value: /b + backendRefs: + - name: servicev1 +--- +kind: BackendLBPolicy +metadata: + name: lbp +spec: + targetRef: + kind: Service + Name: servicev1 + sessionPersistence: + sessionName: service-cookie + type: Cookie +``` + +Route rules referencing the same service MUST NOT share persistent sessions (i.e. the same cookie), even if the session persistence is attached to the service via `BackendLBPolicy`, and each route rule should have different persistent sessions. + +1. Curl to `/a` which establishes a persistent session with `servicev1` +2. Curl to `/b` which establishes another persistent session with `servicev1` since the previous session established earlier is not shared with this route path. + +#### Session Naming Collision + +Consider the situation in which two different services have cookie-based session persistence configured with the +same `sessionName`: + +```yaml +kind: HTTPRoute +metadata: + name: split-route +spec: + rules: + - backendRefs: + - name: servicev1 + weight: 50 + - name: servicev2 + weight: 50 +--- +kind: BackendLBPolicy +metadata: + name: lbp-split-route +spec: + targetRef: + kind: Service + Name: servicev1 + sessionPersistence: + sessionName: split-route-cookie + type: Cookie +--- +kind: BackendLBPolicy +metadata: + name: lbp-split-route2 +spec: + targetRef: + kind: Service + Name: servicev2 + sessionPersistence: + sessionName: split-route-cookie + type: Cookie +``` + +This is an invalid configuration as two separate sessions cannot have the same cookie name. Implementations SHOULD +address this scenario in manner they deem appropriate. Implementations MAY choose to reject the configuration, or they +MAY non-deterministically allow one cookie to work (e.g. whichever cookie is configured first). + +#### Traffic Splitting with route rule inline sessionPersistence field + +Consider the scenario where a route is traffic splitting between two backends, and additionally, an inline route rule `sessionPersistence` config is applied: + +```yaml +kind: HTTPRoute +metadata: + name: split-route +spec: + rules: + - backendRefs: + - name: servicev1 + weight: 50 + - name: servicev2 + weight: 50 + sessionPersistence: + sessionName: split-route-cookie + type: Cookie +``` + +In this scenario, session persistence is enabled at route rule level and all services in the traffic split have persistent session. + +That is to say, traffic routing to `servicev1` previously MUST continue to be routed to `servicev1` when cookie is present, and traffic routing to `servicev2` previously MUST continue to be routed to `servicev2` when cookie is present. + +When cookie is not present, such as, a new session, it will be routed based on the `weight` configuration and choose one of the services. + +#### Traffic Splitting with BackendLBPolicy attached to some Backends (not all) + +Consider the scenario where a route is traffic splitting between two backends, and additionally, a +`BackendLBPolicy` with `sessionPersistence` config is attached to one of the services: + +```yaml +kind: HTTPRoute +metadata: + name: split-route +spec: + rules: + - backendRefs: + - name: servicev1 + weight: 50 + - name: servicev2 + weight: 50 +--- +kind: BackendLBPolicy +metadata: + name: lbp-split-route +spec: + targetRef: + kind: Service + Name: servicev1 + sessionPersistence: + sessionName: split-route-cookie + type: Cookie +``` + +In this traffic splitting scenario within a single route rule, this GEP leaves the decision to the implementation. An +implementation MUST choose one of the following: + +1. Apply session persistence configured in `BackendLBPolicy` to `servicev1` and `servicev2` equally +2. Reject the session persistence configured in `BackendLBPolicy` so that `servicev1` does not have session persistence +3. Apply session persistence for only `servicev1`, potentially causing all traffic to eventually migrate to `servicev1` + +This is also described in [Traffic Splitting](#traffic-splitting). + +#### A Service's Selector is Dynamically Updated + +In Kubernetes, it's possible to modify the [selector](https://kubernetes.io/docs/concepts/services-networking/service/#services-in-kubernetes) +of a service after the gateway has established persistent sessions with it. + +```yaml +kind: Service +metadata: + name: my-service +spec: + selector: + app.kubernetes.io/name: MyApp # Service selector can change +``` + +The expected behavior is that the gateway SHOULD retain existing persistent sessions, even if the pod is no longer +selected, and establish new persistent sessions after a selector update. This use case is uncommon and may not be +supported by some implementations due to their current designs. + +### Conformance Details + +TODO + +### Open Questions + +- What happens when session persistence causes traffic splitting scenarios to overload a backend? +- Should we add status somewhere when a user gets into a "risky" configuration with session persistence? +- Should there be an API configuration field that specifies how already established sessions are handled? +- How do implementations drain established sessions during backend upgrades without disruption? + - Do we need a "session draining timeout" as documented by [A55: xDS-Based Stateful Session Affinity for Proxyless gRPC](https://github.com/grpc/proposal/blob/master/A55-xds-stateful-session-affinity.md#background) + defined in this API? +- How do we provide a standard way to communicate that an implementation does not support Route Rule API? + - Do we want something conceptually similar to the `IncompatibleFilters` reason? + +## TODO + +The following are items that we intend to resolve in future revisions: + +- We need to identify and document requirements regarding session draining and migration. +- We need to document sessions with Java in greater detail. Java standardized the API and behavior of session persistence long ago and would be worth examining. +- We need to add a small section on compliance regarding the browser and client relationship. +- We need to finish enumerating all the edge cases in [Edge Case Behavior](#edge-case-behavior) and identify +potential scenarios where session persistence could break so an implementation can implement session persistence in a +predicable way. +- We need to clean up the [Implementations](#implementations) table to make it more organized and readable. +- We need to revisit how to indicate to a user that a `BackendLBPolicy` configuration is being overridden by a route +configuration via a warning status or log. + - This might require addressing as part of an update to [GEP-2648](../gep-2648/index.md). + +## Alternatives + +### SessionPersistence API Alternative + +Taking a different approach, this GEP could design a more specific policy for configuring session persistence. Rather +than containing all load balancing configuration within a single metaresource, we could opt for a more specific design +with a metaresource called `SessionPersistencePolicy`, specifically to handle session persistence configuration. + +The advantage of `SessionPersistencePolicy` is that it is more specific, which may enable a smoother transition to +attaching to routes in the future (see [Route Attachment Future Work](#route-attachment-future-work)). + +```go +// SessionPersistencePolicy provides a way to define session persistence rules +// for a service or route. +type SessionPersistencePolicy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of SessionPersistencePolicy. + Spec SessionPersistencePolicySpec `json:"spec"` + + // Status defines the current state of SessionPersistencePolicy. + Status PolicyStatus `json:"status,omitempty"` +} + +// SessionPersistencePolicySpec defines the desired state of +// SessionPersistencePolicy. +// Note: there is no Override or Default policy configuration. +type SessionPersistencePolicySpec struct { + // TargetRef identifies an API object to apply policy to. + TargetRef gatewayv1a2.PolicyTargetReference `json:"targetRef"` + + // SessionName defines the name of the persistent session token + // (e.g. a cookie name). + // + // +optional + // +kubebuilder:validation:MaxLength=4096 + SessionName String `json:"sessionName,omitempty"` +} +``` + +### HTTPCookie API Alternative + +Alternatively, the API for session persistence could be tightly coupled to cookies rather than being generic as +described in [API Granularity](#api-granularity). The advantage here is the API's ability to offer greater control +through specific cookie attributes and configuration, catering to the needs of advanced users. However, there could be +challenges with implementations adhering to an API that is closely tied to cookies. This alternative could apply to the +current [`BackendLBPolicy`](#api) design or the [`SessionPersistencePolicy`](#sessionpersistence-api-alternative) +alternative. + +The cookie attributes can be defined either as a loosely-typed list of attributes or as strongly-typed attribute fields. +A loosely-typed list approach offers a more flexible specification, particularly when new attributes need to be +introduced. However, loosely-typed lists may not be as user-friendly due to the lack of validation. + +```go +// HttpCookie defines a cookie to achieve session persistence. +type HttpCookie struct { + // Name defines the cookie's name. + // + // +kubebuilder:validation:MaxLength=4096 + Name String `json:"name,omitempty"` + + // CookieAttributes defines the cookie's attributes. + // + // +optional + CookieAttributes []CookieAttribute `json:cookieAttributes` +} + +// CookieAttribute defines the cookie's attributes. +type CookieAttribute map[string][]string +) +``` + +Strongly-typed attribute fields provide a more user-friendly experience by offering stronger validation for each of the +fields. A strongly-type cookie API could be a mix of individual fields and listed attributes. More specifically, we +could separate the key attributes with no value into a list. This approach is taken by [Haproxy Ingress](https://haproxy-ingress.github.io/docs/configuration/keys/#affinity) +with their `session-cookie-keywords` field. This provides flexibility for simple boolean-typed attributes, while +validating attributes that have values. However, this approach may be confusing to users as uses two different API +patterns for cookie attributes. + +```go +// HttpCookie defines a cookie to achieve session persistence. +type HttpCookie struct { + // Name defines the cookie's name. + // + // +kubebuilder:validation:MaxLength=4096 + Name String `json:"name,omitempty"` + + // SameSite defines the cookie's SameSite attribute. + // + // +optional + // +kubebuilder:validation:Enum=Strict;Lax;None + SameSite SameSiteType `json:"sameSite,omitempty"` + // Domain defines the cookie's Domain attribute. + // + // +optional + // +kubebuilder:validation:MaxLength=4096 + Domain String `json:"domain,omitempty"` + + // CookieKeywords defines the cookie's attributes that have no value. + // + // +optional + CookieKeywords []CookieKeyword `json:cookieKeywords` +} + +// CookieKeyword defines the cookie's attributes that have no value. +type CookieKeyword string + +const ( + // CookieKeywordsHttpOnly specifies the HttpOnly cookie attribute. + CookieKeywordsHttpOnly HttpOnlyMode = "HttpOnly" + // CookieKeywordsSecure specifies the Secure cookie attribute. + CookieKeywordsSecure HttpOnlyMode = "Secure" +) +``` + +### Alternate Naming + +This GEP describes session persistence and session affinity as the idea of strong and weak connection persistence respectively. Other technologies use different names or define persistence and affinity differently: + +- Envoy defines [stateful sessions](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/http/stateful_session/cookie/v3/cookie.proto) as what we've defined as session persistence +- Google Cloud Run defines [session affinity](https://cloud.google.com/run/docs/configuring/session-affinity) as what we've defined as session persistence +- Nginx defines [session persistence](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#enabling-session-persistence) as what we've defined as both session persistence and affinity +- Traefik defines [sticky sessions](https://doc.traefik.io/traefik/routing/services/#sticky-sessions) as what we've defined as session persistence +- Apache httpd defines [sticky sessions or stickiness](https://httpd.apache.org/docs/2.4/mod/mod_proxy_balancer.html) as what we've defined as session persistence +- Kubernetes defines [session affinity](https://kubernetes.io/docs/reference/networking/virtual-ips/#session-affinity) based on client IP hashing (same as our session affinity) +- Microsoft Application Gateway defines [session affinity, session persistence, and sticky sessions](https://learn.microsoft.com/en-us/azure/application-gateway/for-containers/session-affinity?tabs=session-affinity-gateway-api) as what we've defined as session persistence + +Though session persistence is a ubiquitous name, session affinity is more inconsistently used. An alternate decision could be made to use a different name for session affinity based on the prevalence of other naming conventions. + +## References + +- [LBPolicy](https://static.sched.com/hosted_files/kccnceu2023/c4/Autoscaling%20Elastic%20Kubernetes%20Infrastructure%20for%20Stateful%20Applications%20using%20Proxyless%20gRPC%20and%20Istio.pdf#page=25) (proposed extension for session persistence API) +- [gRPC Stateful Session Affinity Proposal](https://github.com/grpc/proposal/blob/master/A55-xds-stateful-session-affinity.md) (info on session draining and session persistence in gRPC) +- [Kube-Proxy Session Affinity](https://kubernetes.io/docs/reference/networking/virtual-ips/#session-affinity) +- [GEP-713: Metaresources and PolicyAttachment](../gep-713/index.md) +- [RFC6265](https://www.rfc-editor.org/rfc/rfc6265) +- [Policy Attachment](../../reference/policy-attachment.md) +- [Envoy Session Persistence Design Doc](https://docs.google.com/document/d/1IU4b76AgOXijNa4sew1gfBfSiOMbZNiEt5Dhis8QpYg/edit#heading=h.sobqsca7i45e) +- [Envoy Session Persistence Issue](https://github.com/envoyproxy/envoy/issues/16698) diff --git a/site-src/ko/geps/gep-1619/metadata.yaml b/site-src/ko/geps/gep-1619/metadata.yaml new file mode 100644 index 0000000000..d7d009cf35 --- /dev/null +++ b/site-src/ko/geps/gep-1619/metadata.yaml @@ -0,0 +1,23 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1619 +name: Session Persistence +status: Provisional +authors: + - gcs278 + - sjberman + - robscott +relationships: + seeAlso: + - number: 713 + name: Metaresources and Policy Attachment + description: Defines metaresource and policy attachment API + - number: 2257 + name: Gateway API Duration Format + description: Defines the Duration API field +changelog: + - "https://github.com/kubernetes-sigs/gateway-api/pull/1643" + - "https://github.com/kubernetes-sigs/gateway-api/pull/1889" + - "https://github.com/kubernetes-sigs/gateway-api/pull/1935" + - "https://github.com/kubernetes-sigs/gateway-api/pull/2159" + - "https://github.com/kubernetes-sigs/gateway-api/pull/2634" diff --git a/site-src/ko/geps/gep-1651/index.md b/site-src/ko/geps/gep-1651/index.md new file mode 100644 index 0000000000..967c65d59e --- /dev/null +++ b/site-src/ko/geps/gep-1651/index.md @@ -0,0 +1,420 @@ +# GEP-1651: Gateway Routability + +* Issue: [#1651](https://github.com/kubernetes-sigs/gateway-api/issues/1651) +* Status: Provisional + +(See [status definitions](../overview.md#gep-states).) + +## TLDR + +Allow users to configure a Gateway so that it is only routable within +a specific scope (ie. public/private/cluster) + +## Goals + +- Define a mechanic to set the routability on a Gateway +- Provide a default set of routability options +- Provide a way for vendors to support custom options + +## Non-Goals + +- Per-request/route scope +- Not a lightweight service mesh + +## Introduction + +One of the early feature requests for Knative was the ability to deploy an +application using Knative's HTTP routing support, but make it only available +within the cluster. I want to be able to specify both the "cluster" +(service.namespace.svc) and "external" (service.namespace.example.com). +Gateways using the same GatewayClass on the cluster, but ensure that the +"cluster" service is only routable within the cluster. This would greatly +simplify deployment for users over the instructions we have today. + +Likewise another use case is to provide load balancing capabilities within a virtual +private network. Different IaaS providers offer private load balancers to support +these use cases. + +## API + +We propose adding a new `routability` field under the `spec.infrastructure` stanza of a Gateway. + +### Predefined Routability Values + +Implementations MAY implement the following values for 'routability' and MUST abide by +their defined semantics. + +Value | Scope +-|- +`Public`|The address is routable on the public internet +`Private`|The address is routable inside a private network larger than a single cluster (ie. VPC) and MAY include RFC1918 address space +`Cluster`|The address is routable inside the [cluster's network](https://kubernetes.io/docs/concepts/cluster-administration/networking/#how-to-implement-the-kubernetes-network-model) + +Values can be compared semantically - `Public` has a larger scope than `Private`, while `Private` has a larger scope than `Cluster`. + +### Vendor prefixed values + +Implementations can define custom 'routability' values by specifying a vendor prefix followed +by a slash `/` and a custom name ie. `com.example.com/my-routability`. + +Comparing vendor prefixed scopes with the pre-defined ones in implementation specific. + +### Default Routability + +The default value of `routability` is implementation specific. It is RECOMMENDED that +the default `routability` remains consistent for Gateways with the same +`gatewayClassName`. + +Implementations MUST signal the default routability using the Gateway's `status.addresses`. See 'Status Addresses` +for more details. + +### Mutability + +Implementations MAY prevent end-users from updating the `routability` value of a Gateway. If +updates are allowed the semantics and behaviour will depend on the underlying implementation. + +If a Gateway is mutated but does not support the desired routability it MUST set the conditions +`Accepted`, `Programmed` to `False` with `Reason` set to `UnsupportedRoutability`. Implementations +MAY choose to leave the old Gateway running with the previous generation's configuration. + +### Go + +```go + +// GatewayRoutability represents the routability of a Gateway +// +// The pre-defined values listed in this package can be compared semantically. +// `Public` has a larger scope than `Private`, while `Private` has a larger scope than +// `Cluster`. +// +// Implementations can define custom routability values by specifying a vendor +// prefix followed by a slash '/' and a custom name ie. `dev.example.com/my-routability`. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^Public|Private|Cluster|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-_]+$` +type GatewayRoutability string + +const ( + // GatewayRoutabilityPublic means the Gateway's address MUST + // be routable on the public internet + // + // Implementations MAY support this routability + GatewayRoutabilityPublic GatewayRoutability = "Public" + + // GatewayRoutabilityPrivate means the Gateway's address MUST + // only be routable inside a private network larger than a single + // cluster (ie. VPC) and MAY include the RFC1918 address space + // + // Implementations MAY support this routability + GatewayRoutabilityPrivate GatewayRoutability = "Private" + + // GatewayRoutabilityCluster means the Gateway's address MUST + // only be routable inside the [cluster's network] + // + // Implementations MAY support this routability + // + // [cluster's network](https://kubernetes.io/docs/concepts/cluster-administration/networking/#how-to-implement-the-kubernetes-network-model) + GatewayRoutabilityCluster GatewayRoutability = "Cluster" +) + +type GatewaySpec struct { + // Infrastructure defines infrastructure level attributes about this Gateway instance. + Infrastructure GatewayInfrastructure `json:"infrastructure"` + // ... +} +type GatewayInfrastructure struct { + // Routability allows the Gateway to specify the accessibility of its addresses. Setting + // this property will override the default value defined by the GatewayClass. + // + // If the desired Gateway routability is incompatible with the GatewayClass implementations + // MUST set the condition `Accepted` to `False` with `Reason` set to `UnsupportedRoutability`. + + // The default value of routability is implementation specific and MUST remains consistent for + // Gateways with the same gatewayClassName + // + // Implementations MAY prevent end-users from updating the routability value of a Gateway. + // If updates are allowed the semantics and behaviour will depend on the underlying implementation. + // If a Gateway is mutated but does not support the desired routability it MUST set `Accepted` + // and `Programmed` conditions to `False` with `Reason` set to `UnsupportedRoutability`. + // + // It is RECOMMENDED that in-cluster gateways SHOULD NOT support 'Private' routability. + // Kubernetes doesn't have a concept of 'Private' routability for Services. In the future this may + // change upstream. + // + // +optional + Routability *GatewayRoutability `json:"routability,omitempty"` +} + +type GatewayStatus struct { + // Addresses lists the IP addresses that have actually been + // bound to the Gateway. These addresses may differ from the + // addresses in the Spec, e.g. if the Gateway automatically + // assigns an address from a reserved pool. + // + // Implementations that support Gateway routability MUST include an address + // that has the same routable semantics as defined in the Gateway spec. + // + // Implementations MAY add additional addresses in status, but they MUST be + // semantically less than the scope of the requested scope. For example if a + // user requests a `Private` routable Gateway then an additional address MAY + // have a routability of `Cluster` but MUST NOT include `Public`. + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Addresses []GatewayStatusAddress `json:"addresses,omitempty"` + // ... +} + +type GatewayStatusAddress struct { + // Routability specifies the routable bounds of this address + // Predefined values are: 'Private', 'Public', Cluster + // Other values MUST have a vendor prefix. + // + // Implementations that support Routability MUST populate this + // field + // + // +optional + Routability *GatewayRoutability `json:"routability,omitempty"` + + // ... +} + +type GatewayClassStatus struct { + // Routabilities specifies a list of supported routabilities offered by + // the GatewayClass. The first entry in this list will be the default + // routability used when Gateways of this class are created. + // + // Implementations MAY provide a pre-defined set of GatewayClasses that + // limit the routability choices of a Gateway. + // + // Implementations that support routability MUST populate this list with + // a subset of the pre-defined GatewayRoutability values or vendored + // prefix values. + // + // +optional + // +kubebuilder:validation:MaxItems=8 + // + Routabilities []GatewayRoutability `json:"routabilities"` +} +``` + +### YAML +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: prod-web +spec: + gatewayClassName: example + infrastructure: + routability: Public + listeners: + - protocol: HTTP + port: 80 +``` + +### Semantics + +#### Interaction with GatewayClass + +An infrastructure provider MAY provide a pre-defined set of GatewayClasses that limit the +routability choices of a Gateway. If the desired Gateway routability is incompatible with the +GatewayClass it MUST set the condition `Accepted` to `False` with `Reason` set to `UnsupportedRoutability`. + +If an implementation supports 'routability' then the GatewayClass MUST list the supported +routabilities in the status stanza. The `status.routabilities` MUST contain either +a subset of the pre-defined values mentioned above or contain vendored prefixed values. + +The first value in the list will be used as the default value when Gateways of this class +are created. This can be overridden by setting the Gateway's `spec.infrastructure.routability`. + +#### Unsupported routability & address values + +If a Gateway is unable to provide an address for the desired routability it MUST set the condition `Accepted` +to `False` with `Reason` set to `UnsupportedRoutability` + +#### Status.Addresses + +If a Gateway supports the desired 'routability' implementations MUST populate the `status.addresses` with +an address that has the same routable semantics. The GatewayAddress field `routability` MUST be populated. + +Implementations MAY add additional addresses in status, but they MUST be semantically less than the scope +of the requested scope. For example if a user requests a `Cluster` routable Gateway then the list of addresses +MUST NOT have a routability of `Public` or `Private`. + +We plan on introducing a new type `GatewayStatusAddress` and change Gateway's `status.addresses` to be +`[]GatewayStatusAddress`. This will allow the status address type to evolve separately from the spec address. + +#### In-cluster Gateways and 'Private' Routability + +It is RECOMMENDED that in-cluster gateways SHOULD NOT support 'Private' routability. Kubernetes doesn't have +a concept of 'Private' routability for Services. In the future this may change upstream. + +#### Interaction with Multi-Network Kubernetes + +[Multi-Network Kubernetes](https://github.com/kubernetes/enhancements/pull/3700) +is a sibling SIG working on adding multi-network support to Pods. After reaching out and having a discussion with about this GEP +the consensus is that a Gateway most likely in the future can be tied to a single PodNetwork. Defining this is out of scope for this GEP. + +A second consensus is the Routabilities defined in this GEP don't impact PodNetworks but instead are indicators to LB implementations +on how they should behave. + +## Examples + +#### 1. Request a GatewayAddress that is routable within the same cluster + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: prod-web +spec: + gatewayClassName: example + infrastructure: + routability: Cluster + listeners: + - protocol: HTTP + port: 80 +``` + +#### 2. Request a GatewayAddress with a specific routability and address +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: prod-web +spec: + gatewayClassName: example + infrastructure: + routability: Cluster + listeners: + - protocol: HTTP + port: 80 + addresses: + - value: 10.0.0.8 +``` + +#### 3. Request a GatewayAddress that is routable on the public internet +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: prod-web +spec: + gatewayClassName: example + infrastructure: + routability: Public + listeners: + - protocol: HTTP + port: 80 +``` + +#### 4. Request a GatewayAddress that is a cloud provider's VPC +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: prod-web +spec: + gatewayClassName: example + infrastructure: + routability: Private + listeners: + - protocol: HTTP + port: 80 +``` + +## Alternatives + +### Introducing new GatewayAddress Types + +We could introduce additional `AddressTypes` (ie. `ClusterLocalIPAddress`) but +this would lead to a combinatorial explosion as new dimensions (ie. IPv6) are +introduced. + +From: [https://github.com/kubernetes-sigs/gateway-api/pull/1653#issuecomment-1451246877](https://github.com/kubernetes-sigs/gateway-api/pull/1653#issuecomment-1451246877) + +> Although this makes sense in isolation, I'm worried about the long term impacts this could have. In my opinion, ClusterLocal is a modifier, not exactly an address type. For example, it's possible in the future that we'll have a way to provision cluster-local DNS names, we may want to use the same kind of mechanism to request a ClusterLocal DNS name for the Gateway. +> +> It's also possible that users will want to explicitly request an IP Families (v4, v6, or both). I'd really hate to get into a situation where we have the following options: +> +> - IPAddress +> - IPv4Address +> - IPv6Address +> - ClusterLocalIPAddress +> - ClusterLocalIPv4Address +> - ClusterLocalIPv6Address +> +> For each dimension we avoid adding a separate field for and instead try to embed into a single name, we risk this kind of name explosion. Of course none of the above even begins to cover my idea of NetworkLocal which could further complicate this. + +### Scope/reachability/routability field on GatewayAddress + +This would allow Gateways to have multiple scopes. + +From: [https://github.com/kubernetes-sigs/gateway-api/pull/1653#issuecomment-1486271913](https://github.com/kubernetes-sigs/gateway-api/pull/1653#issuecomment-1486271913) +> The obvious application for multiple scopes seems to be saving on boilerplate, which is a win, but are there are any other advantages to allowing one Gateway to have multiple scopes? +> +> Multiple scopes Pros: +> +> Allows a single Gateway to express multiple networks, saving on needing to attach HTTPRoutes to multiple Gateways for each network scope. +> +> Multiple scopes Cons: +> +> Complicates the Gateway's purpose. Instead of one Gateway being one set of Listeners, now a Gateway is two sets of listeners that have a totally different scope (and presumably, security context). Personally, I'm also concerned how this will interact with other features like merging and preprovisioning that GEP-1867: Per-Gateway Infrastructure #1868 will allow. + +### Adding `routability` attribute to GatewayClass + +See [Prior Art - Multiple Gateways Classes](#multiple-gateway-classes) + +## Survey of Prior Art + +These alternatives are a survey of existing approaches to support cluster +local Gateways. Most are implementation specific and are not portable. + +### Special annotation/label + +Istio let's you specify an annotation `networking.istio.io/service-type` to +change the underlying Kubernetes Service type to make it a ClusterIP type. + +### Re-use of AddressType Hostname + +Istio let's you re-use existing Gateway deployments by setting the address +type to `Hostname` and the value to the Istio ingress Kubernetes Service. If an +operator configures the Istio deployment to support cluster local traffic a +Gateway implementation can select it using the `HostName` attribute. + +### Multiple Gateway Classes + +Some implementations support multiple deployments on a single cluster where each maps to a +GatewayClass. One of these deployments can be configured to serve cluster local traffic. This is +sub-optimal because this is implementation specific and the end-user is effectively managing the +deployments themselves rather than infrastructure being automatically provisioned. + +Likewise, infrastructure providers may provide a fixed set of GatewayClasses with unique and fixed +routability. Thus GatewayClass name is a viable option to control routability. There may be a +non-zero cost when requiring additional GatewayClasses - but this depends on the implementation. + +Additionally, if more attributes are added to GatewayClass to constrain Gateways in some +form this leads to a combinatorial number of GatewayClassNames. For example, `foo-public` and +`foo-cluster` are two GatewayClasses surfacing the values of a single attribute `routability`. +Let's say we want to enforce address types to just IP then our `gatewayClassName` would be: + +- `foo-public-ipv4` +- `foo-public-ipv6` +- `foo-cluster-ipv4` +- `foo-cluster-ipv6` + +This may not be as flexible for end-users compared to configuring `routability` when creating +a Gateway. + +As mentioned in [howardjohn's comment on GEP-1651: Gateway Routability](https://github.com/kubernetes-sigs/gateway-api/pull/1653#issuecomment-1429992160): +> having the ability to configure things at a higher level seems nice for Gateway, but being able to configure them on a per-Gateway basis remains important. + +## References + +- [Knative - Private Services](https://knative.dev/docs/serving/services/private-services/#configuring-private-services) +- [Initial Gateway GitHub Discussion](https://github.com/kubernetes-sigs/gateway-api/discussions/1247) +- [Istio Support for Private Gateways](https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/#automated-deployment) +- [Envoy Gateway Support for Private Gateways](https://gateway.envoyproxy.io/latest/api/config_types.html#kubernetesservicespec) + diff --git a/site-src/ko/geps/gep-1651/metadata.yaml b/site-src/ko/geps/gep-1651/metadata.yaml new file mode 100644 index 0000000000..e5f7ea1767 --- /dev/null +++ b/site-src/ko/geps/gep-1651/metadata.yaml @@ -0,0 +1,8 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1651 +name: Gateway Routability +status: Provisional +authors: + - dprotaso + - sunjayBhatia diff --git a/site-src/ko/geps/gep-1686/index.md b/site-src/ko/geps/gep-1686/index.md new file mode 100644 index 0000000000..e986ee619f --- /dev/null +++ b/site-src/ko/geps/gep-1686/index.md @@ -0,0 +1,108 @@ +# GEP-1686: Mesh conformance testing plan + +- Issue: [#1686](https://github.com/kubernetes-sigs/gateway-api/issues/1686) +- Status: Standard + +## TLDR + +This testing plan specifies a new set of tests to define a "Mesh" [conformance profile](https://github.com/kubernetes-sigs/gateway-api/issues/1709). + +## Goals + +* Define a strategy for segmenting GAMMA tests from the existing conformance test suite +* Define a set of test scenarios to capture conformance with the GAMMA spec +* Rely on existing tests for non-GAMMA-specific Gateway API conformance + +## Focus + +Currently the GAMMA spec consists of two Gateway API GEPs [defining terminology and goals of Gateway API for service meshes](../gep-1324/index.md) +and specifically [how route resources work in a service mesh context](/geps/gep-1426/). +The goal of the initial conformance testing is to check the essential behavior as defined by GEP-1426, as it differs from the wider Gateway API spec. This GEP focuses on using a `Service` object as an `xRoute` `parentRef` to control how the GAMMA implementation directs traffic to the endpoints specified by the `Services` in `backendRefs` and how the traffic is filtered and modified. + +## Conformance Profile + +GAMMA intends to introduce a "Mesh" [conformance profile](../gep-1709/index.md) to isolate tests specific to East/West functionality from both existing tests focused on North/South functionality and common Gateway API functionality shared by N/S and E/W implementations. A conformance profile is a set of tests that implementations can run to check their conformance to some subset of the Gateway API spec. + +This approach will enable service meshes to certify that an implementation follows the GAMMA spec without requiring a North/South implementation, and importantly avoid any expectation that North/South Gateway API implementations expand their scope to understand GAMMA and E/W traffic flows. + +Leveraging existing tests for common functionality between N/S and E/W implementations will both ensure consistency across Gateway API implementations and help limit the maintenance burden for the conformance testing suite. + +### Support Levels + +Using a conformance profile will enable granular conformance definitions for GAMMA, splitting functionality along the existing Gateway API [support levels](../../concepts/conformance.md?h=conformance+levels#2-support-levels), with required functionality as Core, standardized but optional functionality as Extended, and Implementation-specific for things beyond the current or intended scope of GAMMA configuration. It is expected that some capabilities will begin as Implementation-specific and eventually migrate to Extended or Core conformance as GAMMA matures. + +## Tests + +Testing GAMMA implementations requires both a new suite of test cases as well as refactoring the existing test framework setup. + +### Runner and Setup + +The existing Gateway API conformance tests use a relatively simple implementation to send requests from outside a Kubernetes cluster to a gateway sitting at the edge, [capture the request and response](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/utils/roundtripper/roundtripper.go), and [assert a match against an expected response](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/utils/http/http.go). + +GAMMA conformance tests should still be based around a request/expected response suite, but requests will need to originate from _inside the cluster_, from either the same or different namespace as the target service. Adopting or developing tooling to enable this is being explored in [gateway-api#1340](https://github.com/kubernetes-sigs/gateway-api/issues/1340). + +### Scenarios + +All requests are sent from a client inside the same cluster/mesh and the same `Namespace` +as the `Service` under test. +Test scenarios are largely focused on the `backendRefs` and the +`Namespace` of an `xRoute` resource. + +#### `Service` as `parentRef` + +- Given a simple `HTTPRoute` with a single `backendRef` + - With an explicit `port` in `parentRef` + - Assert that only requests to this `Service` and `port` are directed to the + backend + - Without a `port` in `parentRef` + - Assert that all requests to this `Service` are directed to the backend + +#### Omitted `backendRefs` + +- Given a simple `HTTPRoute` without `backendRefs` + - Assert that requests are directed to the endpoints defined by the `Service` + `parentRef` in its backend role + +#### Only `Services` as frontends are affected + +- Given a simple `HTTPRoute` with a single `backendRef` + - Send requests directly the endpoints of the `parentRef` `Service`'s backend + - Assert that traffic is not affected by the `HTTPRoute` resource + +#### `Namespace`-dependent behavior, producer vs consumer + +A producer `HTTPRoute` is in the same namespace as the `parentRef` `Service` (the +producer). + +- Given a producer `HTTPRoute` + - Assert that traffic from a client in the producer `Namespace` is routed by the + `HTTPRoute` + - Assert that traffic from a client in a different `Namespace` is routed by the + `HTTPRoute` + +A consumer `HTTPRoute` is in the same `Namespace` as the request sender (the +consumer), a different `Namespace` as the `parentRef` `Service`. + +- Given a consumer `HTTPRoute` + - Assert that traffic from the consumer client is routed by the `HTTPRoute` + - Assert that traffic from a client in a different `Namespace` is _not_ routed by the + `HTTPRoute` + +Consumer routes have priority over producer routes. + +- Given both a consumer `HTTPRoute` and a producer `HTTPRoute` + - Assert that traffic from the consumer client is routed by the consumer `HTTPRoute` + - Assert that traffic from a client in a different `Namespace` is routed by + the producer `HTTPRoute` + +#### `xRoute`-specific + +- Given multiple `xRoutes` of different types + - Assert that routes take affect according to the specificity as defined in the spec +- Given an `HTTPRoute` without `matches`, all requests are received at the `Service` endpoints as if no `HTTPRoute` existed +- Given an `HTTPRoute` with `matches`, unmatched requests are dropped with a 404 + +#### Filters + +Filters have the same effects on requests as any implementation. Gateway API conformance test framework can be +refactored to extract checks on filter behavior for use on both GAMMA and Gateway API tests. diff --git a/site-src/ko/geps/gep-1686/metadata.yaml b/site-src/ko/geps/gep-1686/metadata.yaml new file mode 100644 index 0000000000..b87e0b1e9d --- /dev/null +++ b/site-src/ko/geps/gep-1686/metadata.yaml @@ -0,0 +1,15 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1686 +name: Mesh conformance testing plan +status: Standard +authors: + - michaelbeaumont + - mikemorris + - howardjohn + - kflynn +relationships: + extends: + - number: 1324 + name: Service Mesh in Gateway API + description: Adds initial Mesh conformance testing plan diff --git a/site-src/ko/geps/gep-1709/index.md b/site-src/ko/geps/gep-1709/index.md new file mode 100644 index 0000000000..b4e29acc92 --- /dev/null +++ b/site-src/ko/geps/gep-1709/index.md @@ -0,0 +1,689 @@ +# GEP-1709: Conformance Profiles + +* Issue: [#1709](https://github.com/kubernetes-sigs/gateway-api/issues/1709) +* Status: Standard + +## Important Notes + +Unlike our APIs, CRDs, or `gwctl` conformance profiles and their reports are +not user facing in the traditional sense. As trends in Gateway API utilization +grow and change, it may make sense to adjust how profiles work to align better +with what implementations are doing. As such conformance profiles (that is, +the test suite and the reports) might be subject to backwards incompatible +changes at times in ways the rest of the API wouldn't be (e.g. significant +features may need to be added or removed on a profile). + +## TLDR + +Add high level profiles for conformance tests which implementations can select +when running the conformance test suite. Also add opt-in automated conformance +reporting to the conformance test suite to report conformance results back to +the Gateway API project and receive recognition (e.g. badges). + +## Goals + +- Add high-level profiles which downstream implementations can subscribe to in + order to run tests for the associated supported feature sets. +- Add a reporting mechanism where conformance results can be reported back to + the Gateway API project and provide "badges" to visibly decorate the + implementations as conformant according to their profiles. +- Expand conformance testing documentation significantly so that it becomes the + "landing zone" for new prospective implementations and provides a clear and + iterative process for how to get started implementing Gateway API support. + +## Non-Goals + +- We want to avoid adding any infrastructure for the reporting mechanism if + feasible. +- For this iteration we don't want to add configuration files for conformance + tests, instead leaving that to future iterations and working on the raw + machinery here (see [alternatives considered](#alternatives-considered)). +- For this iteration we don't want to add container images for conformance test + runs, instead leaving that to future iterations (see + [alternatives considered](#alternatives-considered). + +## Introduction + +Since our conformance test suite was conceived of it's been our desire to +provide simple high level profiles that downstream implementations can +subscribe to. + +Today we have `SupportedFeatures` which get us some of what we want in terms of +easily configuring the conformance test suite, but in this GEP we will describe +taking that a step further (and a level higher) to create named profiles which +indicate a "level of conformance" which implementations can prove they satisfy +and receive certification for. + +An API will be provided as the format for conformance test reports. We will +provide tooling to assist with the reporting and certification process of +submitting those reports and displaying the results. + +## API + +The API for conformance profiles will include an API resource called +`ConformanceReport` which will be at the center of a workflow that +implementations can opt into to generate and submit those resources. + +The workflow implementers will follow will include the following high-level +steps: + +1. select a [profile](#profiles) +2. [integrate](#integration) tests in the downstream project +3. [report results and get certified](#certification) + +The goal is to make selecting a conformance profile as simple and automatic of a +process as feasible and support both the existing command line integration +approach (e.g. `go test`) as well as a [Golang][go] approach using the +conformance suite as a library. + +[go]:https://go.dev + +### Profiles + +"Profiles" are effectively categories which represent the high-level grouping of +tests related to some feature (or feature set) of Gateway API. When conformance +is reported using one of these profiles extra features can be covered according +to support levels: + +- `core` +- `extended` + +> **NOTE**: `implementation-specific` doesn't really have much in the way of +> tests today, but it is something users want to be able to display. We leave +> door open for it later and mention it in the [alternatives +> considered](#alternatives-considered) section below. + +We will start with the following named profiles: + +- `HTTP` +- `TLSPassthrough` + +These profiles correspond with `*Route` type APIs that we currently have tests +for. As the tests roll in, we'll also eventually have: + +- `UDP` +- `TCP` +- `GRPC` + +> **NOTE**: In time we may have higher level groupings, like `Layer4` (which +> would include at least `TCP` and `UDP`) but feedback from the community has +> been strong for a preference on the `*Route` level (see the +> [alternatives considered](#alternatives-considered) for some more notes on +> this) for the moment. + +> **NOTE**: APIs that are referenced to or by `*Route` APIs will be tested as +> a part of a profile. For instance, running the `HTTP` profile will also run +> tests for `GatewayClass` and `Gateway` implicitly as these are required +> components of supporting `HTTP`. + +The technical implementation of these profiles is very simple: effectively a +"profile" is a static compilation of existing [SupportedFeatures][feat] which +represent the named category. Features that aren't covered under a "core" level +of support are opt-in. + +[feat]:https://github.com/kubernetes-sigs/gateway-api/blob/c61097edaa3b1fad29721e787fee4b02c35e3103/conformance/utils/suite/suite.go#L33 + +### Integration + +Integrating the test suite into your implementation can be done using one of +the following methods: + +- The [go test][go-test] command line interface which enables projects of any + language to run the test suite on any platform [Golang][go] supports. +- Using the conformance test suite as a [Golang library][lib] within an already + existing test suite. + +> **NOTE**: Usage as a library is already an established colloquialism in the +> community, this effort simply intends to make that more official. + +Conformance profiles are passed as arguments when running the test suite. For +instance when running via command line: + +```console +$ go test ./conformance/... -args -gateway-class=acme -conformance-profile=Layer7 +``` + +Or the equivalent configuration using the Golang library: + +```go +cSuite, err := suite.New(suite.Options{ + GatewayClassName: "acme", + Profiles: sets.New(Layer7), + // other options +}) +require.NoError(t, err, "misconfigured conformance test suite") +cSuite.Setup(t) + +for i := 0; i < len(tests.ConformanceTests); i++ { + test := tests.ConformanceTests[i] + test.Run(t, cSuite) +} +``` + +> **NOTE**: In the `suite.Options` above it's still possible to add `SkipTests` +> but when used in conjunction with `Profile` this will result in a report that +> the profile is not valid for reporting. Implementations in this state may be +> able to report themselves as "in progress", see the +> [certification section](#certification) for details. + +Alternatively for an `Extended` conformance profile where not all of the +features are implemented (as described in the [profiles](#profiles) section +above): + +```console +$ go test ./conformance/... -args \ + -gateway-class=acme \ + -conformance-profiles=HTTP,TCP \ + -unsupported-features=HTTPResponseHeaderModification,HTTPRouteMethodMatching,HTTPRouteQueryParamMatching, +``` + +Or the equivalent configuration using the Golang library: + +```go +cSuite, err := suite.New(suite.Options{ + GatewayClassName: "acme", + Profiles: sets.New( + HTTP, + TCP, + ), + UnsupportedFeatures: sets.New( + suite.SupportHTTPResponseHeaderModification, + suite.SupportHTTPRouteMethodMatching, + suite.SupportHTTPRouteQueryParamMatching, + ), + // other options +}) +require.NoError(t, err, "misconfigured conformance test suite") +cSuite.Setup(t) + +for i := 0; i < len(tests.ConformanceTests); i++ { + test := tests.ConformanceTests[i] + test.Run(t, cSuite) +} +``` + +> **NOTE**: You can't disable features that are `Core` conformance as `Core` is +> a minimum requirement for the profile to be considered fulfilled. + +Some implementations may support more or less extended features than others, +so in some cases it could be cumbersome to have to list ALL features that you +_don't_ support so we optionally and inversely allow `SupportedFeatures` so +you can pick which option makes sense to you, and under the hood the +expressions will compile to the same overall list: + +```go +cSuite, err := suite.New(suite.Options{ + GatewayClassName: "acme", + Profiles: sets.New( + HTTP, + TCP, + ), + SupportedFeatures: sets.New( + suite.SupportHTTPRouteMethodMatching, + ), + // other options +}) +``` + +> **NOTE**: The `UnsupportedFeatures` and `SupportedFeatures` fields are +> mutually exclusive. + +So to have your YAML report include details about extended features you support +you must either opt-in using `SupportedFeatures` to the exact features you +support, or opt-out of the features you _don't_ support using +`UnsupportedFeatures`. + +Once an implementation has integrated with the conformance test suite, they can +move on to [certification](#certification) to report the results. + +[go-test]:https://go.dev/doc/tutorial/add-a-test +[go]:https://go.dev +[lib]:https://pkg.go.dev/sigs.k8s.io/gateway-api@v0.6.2/conformance/utils/suite + +### Implementation mode + +The certification process runs against an implementation using a specific mode, +specified in the final report's "mode" field. A "mode" is intended to capture situations +where a Gateway API implementation may have different features and capabilities +depending on how it is deployed (e.g. an implementation might be deployed with an +external, OR internal load balancer, and have different capabilities depending on +the mode chosen). The modes are implementation-specific, and no upstream mode is +defined, except for `default`, which is used in case no mode is specified. + +### Gateway API version and channel + +The certification is related to a specific API version and a specific channel, +therefore such information must be included in the final report. At test suite +setup time, the conformance profile machinery gets all the CRDs with the field +`.spec.group` equal to `gateway.networking.k8s.io`, and for each of them checks +the annotations `gateway.networking.k8s.io/bundle-version` and +`gateway.networking.k8s.io/channel`. If there are `CRD`s with different +versions, the certification fails specifying that it's not possible to run the +tests as there are different Gateway API versions installed in the cluster. If +there are CRDs with different channels, the certification fails specifying that +it's not possible to run the tests as there are different Gateway API channels +installed in the cluster. If all the Gateway API `CRD`s have the same version +and the same channel, the tests can be run and the detected version and channel +will be set in the `gatewayAPIVersion` and `gatewayAPIChannel` fields of +the final report. Furthermore, the suite must run all the experimental tests when +the channel is `experimental`, and the related features are enabled. + +In addition to the `CRD`s version, the suite needs to check its version in +relation to the `CRD`s one. To do so, a new `.go` file containing the current +Gateway API version is introduced in the project and compiled with the +conformance profile suite: + +```go +const GatewayAPIVersion = "0.7.0" +``` + +At test suite setup time the conformance profile suite checks the `CRD`s version +and the suite version; if the two versions differ, the certification fails. A +new generator will be introduced in the project to generate the aforementioned +`.go` file starting from a VERSION file contained in the root folder. Such a +VERSION file contains the semver of the latest release and is manually bumped at +release time. The script hack/verify-all.sh will be updated to ensure the +generated `.go` file is up to date with the VERSION file. + +Implementations will be able to report their conformance testing results using +our [reporting process](#reporting-process). Implementations will be able to +visibly demonstrate their conformance results on their downstream projects and +repositories using our [certification process](#certification-process). + +## Reporting process + +When conformance tests are executed an argument can be provided to the test +suite to emit `ConformanceReport` resource with the test results. This resource +can be configured to emit to the test output itself, or to a specific file. + +The following is an example report: + +```yaml +apiVersion: v1alpha1 +kind: ConformanceReport +implementation: + organization: acme + project: operator + url: https://acme.com + contact: + - @acme/maintainers + version: v1.0.0 +date: "2023-02-28 20:29:41+00:00" +gatewayAPIVersion: v0.8.0 +gatewayAPIChannel: experimental +mode: default +profiles: +- name: http + core: + result: success + summary: "all core functionality passed" + statistics: + passed: 20 + skipped: 0 + failed: 0 + extended: + result: success + summary: "all extended features supported" + statistics: + passed: 8 + skipped: 0 + failed: 0 + supportedFeatures: + - ExtendedFeature1 + - ExtendedFeature2 + - ExtendedFeature3 + - ExtendedFeature4 + - ExtendedFeature5 +- name: tcp + core: + result: success + summary: "all core functionality passed" + statistics: + passed: 4 + skipped: 0 + failed: 0 + extended: + result: skipped + summary: "some extended features supported" + statistics: + passed: 2 + skipped: 0 + failed: 0 + supportedFeatures: + - ExtendedFeature1 + - ExtendedFeature2 + unsupportedFeatures: + - ExtendedFeature3 +``` + +> **WARNING**: It is an important clarification that this is NOT a full +> Kubernetes API. It uses `TypeMeta` for some fields that made sense to re-use +> and were familiar, but otherwise has its own structure. It is not a [Custom +> Resource Definition (CRD)][crd] nor will it be made available along with our +> CRDs. It will be used only by conformance test tooling. + +> **NOTE**: The `implementation` field in the above example includes an +> `organization` and `project` field. Organizations can be an open source +> organization, an individual, a company, e.t.c.. Organizations can +> theoretically have multiple projects and should submit separate reports for +> each of them. + +> **NOTE**: The `contact` field indicates the GitHub usernames or team +> names of those who are responsible for maintaining this file, so they can be +> easily contacted when needed (e.g. for relevant release announcements +> regarding conformance, e.t.c.). Optionally, it can be an email address or +> a support URL (e.g. GitHub new issue page). + +The above report describes an implementation that just released `v1`, uses gateway +API `v0.8.0` `experimental` channel, and has `HTTP` `core` and `extended` and `TCP` +core and partial `extended` support in `default` mode. + +### Multiple reports + +Multiple `ConformanceReports` can be stored as a list of reports for a specific +Gateway API version. The following shows previous releases of the `acme`/`operator` +implementation and its feature progression: + +```yaml +apiVersion: v1alpha1 +kind: ConformanceReport +implementation: + organization: acme + project: operator + url: https://acme.com + contact: + - @acme/maintainers + version: v0.9.0 +date: "2023-02-28 20:29:41+00:00" +gatewayAPIVersion: v0.8.0 +gatewayAPIChannel: standard +mode: default +profiles: +- name: http + core: + result: success + summary: "some core functionality passed" + statistics: + passed: 18 + skipped: 2 + failed: 0 + skippedTests: + - CoreTest8 + - CoreTest15 + extended: + result: success + summary: "some extended features supported" + statistics: + passed: 8 + skipped: 0 + failed: 0 + supportedFeatures: + - ExtendedFeature1 + - ExtendedFeature2 + unsupportedFeatures: + - ExtendedFeature3 + - ExtendedFeature4 + - ExtendedFeature5 +``` + +```yaml +apiVersion: v1alpha1 +kind: ConformanceReport +implementation: + organization: acme + project: operator + url: https://acme.com + contact: + - @acme/maintainers + version: v1.0.0 +date: "2023-06-1 20:29:41+00:00" +gatewayAPIVersion: v1.0.0 +gatewayAPIChannel: experimental +mode: default +profiles: +- name: http + core: + result: success + summary: "all core functionality passed" + statistics: + passed: 20 + skipped: 0 + failed: 0 + extended: + result: success + summary: "all extended features supported" + statistics: + passed: 8 + skipped: 0 + failed: 0 + supportedFeatures: + - ExtendedFeature1 + - ExtendedFeature2 + - ExtendedFeature3 + unsupportedFeatures: + - ExtendedFeature4 + - ExtendedFeature5 +- name: tcp + core: + result: success + summary: "all core functionality passed" + statistics: + passed: 4 + skipped: 0 + failed: 0 + extended: + result: skipped + summary: "some extended features supported" + statistics: + passed: 2 + skipped: 0 + failed: 0 + supportedFeatures: + - ExtendedFeature1 + - ExtendedFeature2 + unsupportedFeatures: + - ExtendedFeature3 +``` + +> **NOTE**: In the above you can see the `acme` implementation's progression. In +> their release `v0.9.0` they had started adding `HTTP` support and added the +> conformance tests to CI, but they were still skipping some core tests. In +> their next release `v1.0.0` they completed adding `HTTP` `Core` +> functionality (and even added three extended features), and also added +> `TCP` functionality with `Core` and partial `Extended` support. + +> **NOTE**: Implementations **MUST** report for a specific release version +> (e.g. `v0.7.1`) and not use branches or Git SHAs. Some exceptions will be +> made for initial reports to help make it easier for implementations to get +> started, but as we move to standard everyone should be reporting on specific +> releases. + +Creating a pull request to add the `ConformanceReport` will start the +[certification process](#certification-process). + +> **NOTE**: No verification process (to prevent intentionally incorrect +> conformance results) will be implemented at this time. We expect that this wont +> be an issue in our community and even if someone were to try and "cheat" on +> the reporting the reputation loss for being caught would make them look very +> bad and would not be worth it. + +[crd]:https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/ + +### Reports submission + +Implementers can create as many reports as they want, with different API versions, +API channels, modes, and implementation versions. The reports can be submitted upstream +by creating a pull request to the Gateway API repository. The reports folder tree +is the following: + +```console +|-- conformance/reports +| |-- v1.0 +| | |-- acme-operator +| | | |-- README.md +| | | |-- standard-v2.13-default-report.yaml +| |-- v1.1 +| | |-- acme-operator +| | | |-- README.md +| | | |-- standard-v2.14-default-report.yaml +| | | |-- standard-v2.14-with-the-lot-report.yaml +| | | |-- extended-v2.14-with-the-lot-report.yaml +| | |-- umbrella-operator +| | | |-- README.md +| | | |-- standard-v1.8-default-report.yaml +``` + +The main folder `conformance/reports` contains a set of sub-folders, each for a +Gateway API version. Implementors will create their project folder in all the Gateway +API version folders for which they have a supported implementation. The implementors +folder contains the following set of files: + +* `README.md`: contains general information about the implementation, a table of + contents, and the instructions to reproduce the claimed report. +* `---report.yaml`: the report + generated by the conformance test suite for the specific mode. + +#### README.md structure + +The README.md files SHOULD be structured in the following way (enrichment from +implementors is allowed, even though the minimum content is described below): + +```md +# Acme operator + +General information about the Acme/operator project + +## Table of contents + +| API channel | Implementation version | Mode | Report | +|-------------|------------------------|------|--------| +| | | | | +| | | | | +| | | | | + +## To reproduce + +Instructions on how to reproduce the claimed report. +``` + +Each row of the table of contents MUST correspond to an uploaded report and contains +the most implementation version and the mode. An example follows: + +| API channel | Implementation version | Mode | Report | +|--------------|------------------------|--------------|-----------------------------------------------| +| standard | v2.15 | default | ./standard-v2.15-default-report.yaml | +| standard | v2.16 | default | ./standard-v2.16-default-report.yaml | +| experimental | v2.16 | with-the-lot | ./experimental-v2.16-with-the-lot-report.yaml | + +> **NOTE**: the column `Report` contains the link to the corresponding uploaded report. + +> **NOTE**: This table of contents could be improved in the future with a link to +> proof of conformance, such as artifacts containing logs. + +## Certification Process + +The raw report data of the `ConformanceReports` _is predominantly meant for machine +consumption_. Report data will be compiled into human-friendly displays during an +automated certification process. + +Certification starts with the pull request described during the [reporting +process](#reporting-process). Once the `ConformanceReport` is created or +updated a display layer in the implementations page will need to be updated to +point to the new data. + +> **NOTE**: The `ConformanceReport` API will be defined in Golang like our +> other `apis/` so that we can utilize build tags from kubebuilder for defaults +> and validation, and so that there exists a common Golang type for it in the +> conformance test suite. When PRs are created the Gateway API repositories' +> CI will run linting and validation against the reports. + +Maintainers will provide [badges][bdg] to implementations at the end of the process +which link to the implementations page for that specific implementation and can +be easily added via markdown to Git repositories. + +[impl]:../../implementations.md +[bdg]:https://shields.io + +## Alternatives Considered + +### Conformance Test Configuration File + +Conformance testing is currently done mainly through command line with +`go test` or via use of the conformance test suite as a library in Golang +projects. We considered whether adding the alternative to provide a +configuration file to the test suite would be nice, but we haven't heard +any specific demand for that from implementors yet so we're leaving the +idea here for later iterations to consider. + +### Conformance Test Container Image + +Providing a container image which could be fed deployment instructions for an +implementation was considered while working on this GET but it seemed like a +scope all unto itself so we're avoiding it here and perhaps a later iteration +could take a look at that if there are asks in the community. + +### Implementation-Specific Reporting + +Users have mentioned the desire to report on `implementation-specific` features +they support as a part of conformance. At the time of writing, there's not much +in the way of structure or testing for us to do this with but we remain open to +the idea. The door is left open in the `ConformanceReport` API for a future +iteration to add this if desired, but it probably warrants its own GEP as we +need to make sure we have buy-in from multiple stakeholders with different +implementations that are implementing those features. + +### High-Level Profiles + +We originally started with two high-level profiles: + +* `Layer4` +* `Layer7` + +However, the overwhelming feedback from the community was to go a step down and +define profiles at the level of each individual API (e.g. `HTTPRoute`, +`TCPRoute`, `GRPCRoute`, e.t.c.). One of the main reasons for this was that we +already have multiple known implementations of Gateway API which only support +a single route type (`UDPRoute`, in particular as it turns out). + +We may consider in the future doing some of these higher-level profiles if +there's a technical reason or strong desire from implementers. + +## Graduation Criteria + +The following are items that **MUST** be resolved to move this GEP to +`Standard` status (and before the end of the probationary period): + +- [x] some kind of basic level of display for the report data needs to exist. + It's OK for a more robust display layer to be part of a follow-up effort. + - for now we ended up with badges in our implementations page. We have + [another effort](https://github.com/kubernetes-sigs/gateway-api/issues/2550) + underway to build an even better display layer, but we consider this + additive and the current display is sufficient for moving the project to + standard. +- [x] initially we were OK with storing reports in the Git repository as files. + While this is probably sufficient during the `Experimental` phase, we need to + re-evaluate this before `Standard` and see if this remains sufficient or if + we want to store the data elsewhere. + - During the experimental phase this has not caused any significant issues, + so for the purposes of calling this standard we're going to move forward + as-is. It should be straightforward and reasonable to change the storage + mechanism later as needs arise. +- [x] We have been actively [gathering feedback from SIG + Arch][sig-arch-feedback]. Some time during the `experimental` phase needs to + be allowed to continue to engage with SIG Arch and incorporate their feedback + into the test suite. + - SIG Arch did not have any significant feedback during the experimental + phase. In the same timespan the Network Policy group has started using our + test suite and APIs as well, so it seems the overall approach has obvious + merit, and doesn't appear to be redundant. +- [x] Finalize the report organization structure based on feedback during the + experimental phase. +- [x] Base documentation must exist for implementations to run the tests via + the CLI and via the Golang library. + +[sig-arch-feedback]:https://groups.google.com/g/kubernetes-sig-architecture/c/YjrVZ4NJQiA/m/7Qg7ScddBwAJ + +## References + +- https://github.com/kubernetes-sigs/gateway-api/issues/1709 +- https://github.com/kubernetes-sigs/gateway-api/issues/1329 diff --git a/site-src/ko/geps/gep-1709/metadata.yaml b/site-src/ko/geps/gep-1709/metadata.yaml new file mode 100644 index 0000000000..c1abf8aff8 --- /dev/null +++ b/site-src/ko/geps/gep-1709/metadata.yaml @@ -0,0 +1,9 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1709 +name: Conformance Profiles +status: Standard +authors: + - shaneutt + - mlavacca + - arkodg diff --git a/site-src/ko/geps/gep-1713/index.md b/site-src/ko/geps/gep-1713/index.md new file mode 100644 index 0000000000..f51f044dda --- /dev/null +++ b/site-src/ko/geps/gep-1713/index.md @@ -0,0 +1,612 @@ +# GEP-1713: ListenerSets - Standard Mechanism to Merge Multiple Gateways + +* Issue: [#1713](https://github.com/kubernetes-sigs/gateway-api/issues/1713) +* Status: Experimental + +(See [status definitions](../overview.md#gep-states).) + +## Introduction + +The `Gateway` Resource is a point of contention since it is the only place to attach listeners with certificates. We propose a new resource called `ListenerSet` to allow a shared list of listeners to be attached to a single `Gateway`. + +## Goals +- Define a mechanism to merge listeners into a single `Gateway` +- Attaching listeners to `Gateways` in different namespaces +- Standardize merging multiple lists of Listeners together ([\#1863](https://github.com/kubernetes-sigs/gateway-api/pull/1863)) +- Increase the number of Gateway Listeners that are supported ([\#2869](https://github.com/kubernetes-sigs/gateway-api/issues/2869)) + +## Future Potential Goals (Beyond the GEP) + +From [Gateway Hierarchy Brainstorming](https://docs.google.com/document/d/1qj7Xog2t2fWRuzOeTsWkabUaVeOF7_2t_7appe8EXwA/edit#heading=h.w311n4l5qmwk): + +- Provide a mechanism for third party components to generate listeners and attach them to a Gateway ([\#1863](https://github.com/kubernetes-sigs/gateway-api/pull/1863)) +- Delegate TLS certificate management to App Owners and/or different namespaces ([\#102](https://github.com/kubernetes-sigs/gateway-api/issues/102), [\#103](https://github.com/kubernetes-sigs/gateway-api/issues/103)) +- Delegate domains to different namespaces, but allow those namespace to define TLS and routing configuration within those namespaces with Gateway-like resources ([\#102](https://github.com/kubernetes-sigs/gateway-api/issues/102), [\#103](https://github.com/kubernetes-sigs/gateway-api/issues/103)) +- Enable admins to delegate SNI-based routing for TLS passthrough to other teams and/or namespaces ([\#3177](https://github.com/kubernetes-sigs/gateway-api/discussions/3177)) (Remove TLSRoute) +- Simplify L4 routing by removing at least one of the required layers (Gateway \-\> Route \-\> Service) +- Delegate routing to namespaces based on path prefix (previously known as [Route delegation](https://github.com/kubernetes-sigs/gateway-api/issues/1058)) +- Static infrastructure attachment ([\#3103](https://github.com/kubernetes-sigs/gateway-api/discussions/3103\#discussioncomment-9678523)) + +## Use Cases & Motivation + +Knative generates on demand per-service certificates using HTTP-01 challenges. +There can be O(1000) Knative `Services` in the cluster which means we have O(1000) distinct certificates. +Thus updating a single `Gateway` resource with this many certificates is a contention point and inhibits horizontal scaling of our controllers. +[Istio Ambient](https://istio.io/v1.15/blog/2022/introducing-ambient-mesh/), similarly, creates a listener per Kubernetes service. + +More broadly, large scale gateway users often expose `O(1000)` domains, but are currently limited by the maximum of 64 `listeners`. + +The spec currently has language to indicate implementations `MAY` merge `Gateways` resources but does not define any specific requirements for how that should work. +https://github.com/kubernetes-sigs/gateway-api/blob/541e9fc2b3c2f62915cb58dc0ee5e43e4096b3e2/apis/v1beta1/gateway_types.go#L76-L78 + +## Feature Details + +We define `ListenerSet` as the name of the feature outlined in this GEP. +The feature will be part of the experimental channel, which implementations can choose to support. All the `MUST` requirements in this document apply to implementations that choose to support this feature. + + +## API + +This proposal introduces a new `ListenerSet` resource that has the ability to attach a set of listeners to multiple parent `Gateways`. + +### Go + +```go +type GatewaySpec struct { + ... + AllowedListeners *AllowedListeners `json:"allowedListeners"` + ... +} + +type AllowedListeners struct { + // +kubebuilder:default={from:Same} + Namespaces *ListenerNamespaces `json:"namespaces,omitempty"` +} + +// ListenerNamespaces indicate which namespaces ListenerSets should be selected from. +type ListenerNamespaces struct { + // From indicates where ListenerSets can attach to this Gateway. Possible + // values are: + // + // * Same: Only ListenerSets in the same namespace may be attached to this Gateway. + // * Selector: ListenerSets in namespaces selected by the selector may be attached to this Gateway.:w + // * All: ListenerSets in all namespaces may be attached to this Gateway. + // * None: Only listeners defined in the Gateway's spec are allowed + // + // +optional + // +kubebuilder:default=None + // +kubebuilder:validation:Enum=Same;None;Selector;All + From *FromNamespaces `json:"from,omitempty"` + + // Selector must be specified when From is set to "Selector". In that case, + // only ListenerSets in Namespaces matching this Selector will be selected by this + // Gateway. This field is ignored for other values of "From". + // + // +optional + Selector *metav1.LabelSelector `json:"selector,omitempty"` +} + +// ListenerSet defines a set of additional listeners to attach to an existing Gateway. +type ListenerSet struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of ListenerSet. + Spec ListenerSetSpec `json:"spec"` + + // Status defines the current state of ListenerSet. + Status ListenerSetStatus `json:"status,omitempty"` +} + +// ListenerSetSpec defines the desired state of a ListenerSet. +type ListenerSetSpec struct { + // ParentRef references the Gateway that the listeners are attached to. + ParentRef ParentGatewayReference `json:"parentRef"` + + // Listeners associated with this ListenerSet. Listeners define + // logical endpoints that are bound on this referenced parent Gateway's addresses. + // + // Listeners in a `Gateway` and their attached `ListenerSets` are concatenated + // as a list when programming the underlying infrastructure. + // + // Listeners should be merged using the following precedence: + // + // 1. "parent" Gateway + // 2. ListenerSet ordered by creation time (oldest first) + // 3. ListenerSet ordered alphabetically by “{namespace}/{name}”. + // + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=64 + Listeners []ListenerEntry `json:"listeners"` + +} +// ListenerEntry embodies the concept of a logical endpoint where a Gateway accepts +// network connections. +type ListenerEntry struct { + // Name is the name of the Listener. This name MUST be unique within a + // ListenerSet. + // + // Name is not required to be unique across a Gateway and ListenerSets. + // Routes can attach to a Listener by having a ListenerSet as a parentRef + // and setting the SectionName + Name SectionName `json:"name"` + + // Hostname specifies the virtual hostname to match for protocol types that + // define this concept. When unspecified, all hostnames are matched. This + // field is ignored for protocols that don't require hostname based + // matching. + // + // Implementations MUST apply Hostname matching appropriately for each of + // the following protocols: + // + // * TLS: The Listener Hostname MUST match the SNI. + // * HTTP: The Listener Hostname MUST match the Host header of the request. + // * HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP + // protocol layers as described above. If an implementation does not + // ensure that both the SNI and Host header match the Listener hostname, + // it MUST clearly document that. + // + // For HTTPRoute and TLSRoute resources, there is an interaction with the + // `spec.hostnames` array. When both listener and route specify hostnames, + // there MUST be an intersection between the values for a Route to be + // accepted. For more information, refer to the Route specific Hostnames + // documentation. + // + // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + // as a suffix match. That means that a match for `*.example.com` would match + // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + // + // +optional + Hostname *Hostname `json:"hostname,omitempty"` + + // Port is the network port. Multiple listeners may use the + // same port, subject to the Listener compatibility rules. + // + // If the port is specified as zero, the implementation will assign + // a unique port. If the implementation does not support dynamic port + // assignment, it MUST set `Accepted` condition to `False` with the + // `UnsupportedPort` reason. + // + // Support: Core + // + // +optional + Port *PortNumber `json:"port,omitempty"` + + // Protocol specifies the network protocol this listener expects to receive. + // + // Support: Core + Protocol ProtocolType `json:"protocol"` + + // TLS is the TLS configuration for the Listener. This field is required if + // the Protocol field is "HTTPS" or "TLS". It is invalid to set this field + // if the Protocol field is "HTTP", "TCP", or "UDP". + // + // The association of SNIs to Certificate defined in GatewayTLSConfig is + // defined based on the Hostname field for this listener. + // + // The GatewayClass MUST use the longest matching SNI out of all + // available certificates for any TLS handshake. + // + // Support: Core + // + // +optional + TLS *GatewayTLSConfig `json:"tls,omitempty"` + + // AllowedRoutes defines the types of routes that MAY be attached to a + // Listener and the trusted namespaces where those Route resources MAY be + // present. + // + // Although a client request may match multiple route rules, only one rule + // may ultimately receive the request. Matching precedence MUST be + // determined in order of the following criteria: + // + // * The most specific match as defined by the Route type. + // * The oldest Route based on creation timestamp. For example, a Route with + // a creation timestamp of "2020-09-08 01:02:03" is given precedence over + // a Route with a creation timestamp of "2020-09-08 01:02:04". + // * If everything else is equivalent, the Route appearing first in + // alphabetical order (namespace/name) should be given precedence. For + // example, foo/bar is given precedence over foo/baz. + // + // All valid rules within a Route attached to this Listener should be + // implemented. Invalid Route rules can be ignored (sometimes that will mean + // the full Route). If a Route rule transitions from valid to invalid, + // support for that Route rule should be dropped to ensure consistency. For + // example, even if a filter specified by a Route rule is invalid, the rest + // of the rules within that Route should still be supported. + // + // Support: Core + // +kubebuilder:default={namespaces:{from: Same}} + // +optional + AllowedRoutes *AllowedRoutes `json:"allowedRoutes,omitempty"` +} + +// ListenerSetStatus defines the observed state of a ListenerSet +type ListenerSetStatus struct { + // Listeners provide status for each unique listener port defined in the Spec. + // + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=64 + Listeners []ListenerEntryStatus `json:"listeners,omitempty"` + + // Conditions describe the current conditions of the ListenerSet. + // + // Implementations should prefer to express ListenerSet conditions + // using the `GatewayConditionType` and `GatewayConditionReason` + // constants so that operators and tools can converge on a common + // vocabulary to describe Gateway state. + // + // Known condition types are: + // + // * "Accepted" + // * "Programmed" + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// ListenerEntryStatus is the status associated with a ListenerEntry. +type ListenerEntryStatus struct { + // Name is the name of the Listener that this status corresponds to. + Name SectionName `json:"name"` + + // Port is the network port that this listener is listening on. + Port PortNumber `json:"port"` + + // SupportedKinds is the list indicating the Kinds supported by this + // listener. This MUST represent the kinds an implementation supports for + // that Listener configuration. + // + // If kinds are specified in Spec that are not supported, they MUST NOT + // appear in this list and an implementation MUST set the "ResolvedRefs" + // condition to "False" with the "InvalidRouteKinds" reason. If both valid + // and invalid Route kinds are specified, the implementation MUST + // reference the valid Route kinds that have been specified. + // + // +kubebuilder:validation:MaxItems=8 + SupportedKinds []RouteGroupKind `json:"supportedKinds"` + + // AttachedRoutes represents the total number of Routes that have been + // successfully attached to this Listener. + // + // Successful attachment of a Route to a Listener is based solely on the + // combination of the AllowedRoutes field on the corresponding Listener + // and the Route's ParentRefs field. A Route is successfully attached to + // a Listener when it is selected by the Listener's AllowedRoutes field + // AND the Route has a valid ParentRef selecting the whole Gateway + // resource or a specific Listener as a parent resource (more detail on + // attachment semantics can be found in the documentation on the various + // Route kinds ParentRefs fields). Listener or Route status does not impact + // successful attachment, i.e. the AttachedRoutes field count MUST be set + // for Listeners with condition Accepted: false and MUST count successfully + // attached Routes that may themselves have Accepted: false conditions. + // + // Uses for this field include troubleshooting Route attachment and + // measuring blast radius/impact of changes to a Listener. + AttachedRoutes int32 `json:"attachedRoutes"` + + // Conditions describe the current condition of this listener. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions"` +} + +// ParentGatewayReference identifies an API object including its namespace, +// defaulting to Gateway. +type ParentGatewayReference struct { + // Group is the group of the referent. + // + // +optional + // +kubebuilder:default="gateway.networking.k8s.io" + Group *Group `json:"group"` + + // Kind is kind of the referent. For example "Gateway". + // + // +optional + // +kubebuilder:default=Gateway + Kind *Kind `json:"kind"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` + + // Namespace is the name of the referent. + // +optional + Name *ObjectName `json:"namespace"` +} +``` + +### YAML + +The following example shows a `Gateway` with an HTTP listener and two child HTTPS `ListenerSets` with unique hostnames and certificates. + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: parent-gateway +spec: + gatewayClassName: example + listeners: + - name: foo + hostname: foo.com + protocol: HTTP + port: 80 +--- +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: ListenerSet +metadata: + name: first-workload-listeners +spec: + parentRef: + name: parent-gateway + kind: Gateway + group: gateway.networking.k8s.io + listeners: + - name: first + hostname: first.foo.com + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: first-workload-cert # Provisioned via HTTP01 challenge +--- +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: ListenerSet +metadata: + name: second-workload-listeners +spec: + parentRef: + name: parent-gateway + kind: Gateway + group: gateway.networking.k8s.io + listeners: + - name: second + hostname: second.foo.com + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: second-workload-cert # Provisioned via HTTP01 challenge +``` +### ListenerEntry + +`ListenerEntry` is currently a copy of the `Listener` struct with some changes +1. `Port` is now a pointer to allow for dynamic port assignment. + +## Semantics + +### Gateway Changes + +An initial experimental release of `ListenerSets` _will have no modifications_ to listener list on the `Gateway` resource. Using `ListenerSets` will require a dummy listener to be configured. + +In a future (potential) release when an implementation supports `ListenerSets`, `Gateways` MUST allow the list of listeners to be empty. Thus the present `minItems=1` constraint on the listener list will be removed. This allows implementations to avoid security, cost etc. concerns with having dummy listeners. +When there are no listeners the `Gateway`'s `status.listeners` should be empty or unset. `status.listeners` is already an optional field. + +Implementations, when creating a `Gateway`, may provision underlying infrastructure when there are no listeners present. The status conditions `Accepted` and `Programmed` conditions should reflect state of this provisioning. + +### Gateway <> ListenerSet Handshake + +By default a `Gateway` MUST NOT allow `ListenerSets` to be attached. Users can enable this behaviour by configuring their `Gateway` to allow `ListenerSet` attachment: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: parent-gateway +spec: + allowedListeners: + - from: Same +``` + +### Route Attaching + +Routes MUST be able to specify a `ListenerSet` as a `parentRef`. Routes can use `sectionName`/`port` fields in `ParentReference` to help target a specific listener. If no listener is targeted (`sectionName`/`port` are unset) then the Route attaches to all the listeners in the `ListenerSet`. + +Routes MUST be able to attach to a `ListenerSet` and it's parent `Gateway` by having multiple `parentRefs` eg: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: httproute-example +spec: + parentRefs: + - name: second-workload-listeners + kind: ListenerSet + sectionName: second +``` + +For instance, the following `HTTPRoute` attempts to attach to a listener defined in the parent `Gateway` using the sectionName `foo`. This is not valid and the route's status `Accepted` condition should be set to `False` + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: httproute-example +spec: + parentRefs: + - name: some-workload-listeners + kind: ListenerSet + sectionName: foo +``` + +To attach to listeners in both a `Gateway` and `ListenerSet` the route MUST have two `parentRefs`: +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: httproute-example +spec: + parentRefs: + - name: second-workload-listeners + kind: ListenerSet + sectionName: second + - name: parent-gateway + kind: Gateway + sectionName: foo +``` + +### Listener Validation + +Implementations MUST treat the parent `Gateway`s as having the merged list of all listeners from itself and attached `ListenerSets`. See 'Listener Precedence' for more details on ordering. +Validation of this list of listeners MUST behave the same as if the list were part of a single `Gateway`. + +From the earlier example the above resources would be equivalent to a single `Gateway` where the listeners are collapsed into a single list. + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: parent-gateway +spec: + gatewayClassName: example + listeners: + - name: foo + hostname: foo.com + protocol: HTTP + port: 80 + - name: first + hostname: first.foo.com + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: first-workload-cert # Provisioned via HTTP01 challenge + - name: second + hostname: second.foo.com + protocol: HTTPS + port: 443 + tls: + mode: Terminate + certificateRefs: + - kind: Secret + group: "" + name: second-workload-cert # Provisioned via HTTP01 challenge +``` + +### Listener Precedence + +Listeners in a `Gateway` and their attached `ListenerSets` are concatenated as a list when programming the underlying infrastructure + +Listeners should be merged using the following precedence: + +1. "parent" Gateway +2. ListenerSet ordered by creation time (oldest first) +3. ListenerSet ordered alphabetically by “{namespace}/{name}”. + +Conflicts are covered in the section 'ListenerConditions within a ListenerSet' + +### Gateway Conditions + +`Gateway`'s `Accepted` and `Programmed` top-level conditions remain unchanged and reflect the status of the local configuration. + +Implementations MUST support a new `Gateway` condition type `AttachedListenerSets`. + +The condition's `Status` has the following values: + +- `True` when `Spec.AllowedListeners` is set and at least one child Listener arrives from a `ListenerSet` +- `False` when `Spec.AllowedListeners` is set but has no valid listeners are attached +- `Unknown` when no `Spec.AllowedListeners` config is present + +Parent `Gateways` MUST NOT have `ListenerSet` listeners in their `status.listeners` conditions list. + +### ListenerSet Conditions + +`ListenerSets` have a top-level `Accepted` and `Programmed` conditions. + +The `Accepted` condition MUST be set on every `ListenerSet`, and indicates that the `ListenerSet` is semantically valid and accepted by its `parentRef`. + +Valid reasons for `Accepted` being `False` are: + +- `NotAllowed` - the `parentRef` doesn't allow attachment +- `ParentNotAccepted` - the `parentRef` isn't accepted (eg. invalid address) +- `ListenersNotValid` - one or more listeners in the set are invalid (or using an unsupported feature) + +The `Programmed` condition MUST be set on every `ListenerSet` and have a similar meaning to the Gateway `Programmed` condition but only reflect the listeners in this `ListenerSet`. + +`Accepted` and `Programmed` conditions when surfacing details about listeners, MUST only summarize the `status.listeners` conditions that are exclusive to the `ListenerSet`. +An exception to this is when the parent `Gateway`'s `Accepted` or `Programmed` conditions transition to `False` + +`ListenerSets` MUST NOT have their parent `Gateway`'s' listeners in the associated `status.listeners` conditions list. + +### ListenerConditions within a ListenerSet + +An implementation MAY reject listeners by setting the `ListenerEntryStatus` `Accepted` condition to `False` with the `Reason` `TooManyListeners` + +If a listener has a conflict, this should be reported in the `ListenerEntryStatus` of the conflicted `ListenerSet` by setting the `Conflicted` condition to `True`. + +Implementations SHOULD be cautious about what information from the parent or siblings are reported to avoid accidentally leaking sensitive information that the child would not otherwise have access to. This can include contents of secrets etc. + +### Policy Attachment + +Policy attachment is [under discussion] in https://github.com/kubernetes-sigs/gateway-api/discussions/2927 + +Similar to Routes, `ListenerSet` can inherit policy from a Gateway. +Policies that attach to a `ListenerSet` apply to all listeners defined in that resource, but do not impact listeners in the parent `Gateway`. This allows `ListenerSets` attached to the same `Gateway` to have different policies. +If the implementation cannot apply the policy to only specific listeners, it should reject the policy. + +## Alternatives + +### Re-using Gateway Resource + +The [first iteration of this GEP](https://github.com/kubernetes-sigs/gateway-api/pull/1863) proposed re-using the `Gateway` resource and introducing an `attachTo` property in the `infrastructure` stanza. + +The main downside of this approach is that users still require `Gateway` write access to create listeners. Secondly, it introduces complexity to future `Gateway` features as GEP authors would have now have to account for merging semantics. + +### New 'GatewayGroup' Resource + +This was proposed in the Gateway Hierarchy Brainstorming document (see references below). The idea is to introduce a central resource that will coalesce Gateways together and offer forms of delegation. + +Issues with this is complexity with status propagation, cluster vs. namespace scoping etc. It also lacks a migration path for existing Gateways to help shard listeners. + +### Use of Multiple Disjointed Gateways + +An alternative would be to encourage users to not use overly large Gateways to minimize the blast radius of any issues. Use of disjoint Gateways could accomplish this but it has the disadvantage of consuming more resources and introducing complexity when it comes to operations work (eg. setting up DNS records etc.) + +### Increase the Listener Limit + +Increasing the limit may help in situations where you are creating many listeners such as adding certificates created using an ACME HTTP01 challenge. Unfortunately this still makes the Gateway a single point of contention. Unfortunately, there will always be an upper bound because of etcd limitations. +For workloads like Knative we can have O(1000) Services on the cluster with unique subdomains. + +### Expand Route Functionality + +For workloads with many certificates one option would be to introduce a `tls` stanza somewhere in the Route types. These Routes would then attach to a single Gateway. Then application operators can provide their own certificates. This probably would require some ability to have a handshake agreement with the Gateway. + +Somewhat related, there was a Route Delegation GEP (https://github.com/kubernetes-sigs/gateway-api/issues/1058) that was abandoned + +## References + +First Revision of the GEP + +- https://github.com/kubernetes-sigs/gateway-api/pull/1863 + +Mentioned in Prior GEPs: + +- https://github.com/kubernetes-sigs/gateway-api/pull/1757 + +Prior Discussions: + +- https://github.com/kubernetes-sigs/gateway-api/discussions/1248 +- https://github.com/kubernetes-sigs/gateway-api/discussions/1246 + +Gateway Hierarchy Brainstorming: + +- https://docs.google.com/document/d/1qj7Xog2t2fWRuzOeTsWkabUaVeOF7_2t_7appe8EXwA/edit diff --git a/site-src/ko/geps/gep-1713/metadata.yaml b/site-src/ko/geps/gep-1713/metadata.yaml new file mode 100644 index 0000000000..9d0aac9942 --- /dev/null +++ b/site-src/ko/geps/gep-1713/metadata.yaml @@ -0,0 +1,17 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1713 +name: XListenerSets (Standard Mechanism to Merge Gateways) +status: Experimental +authors: + - dprotaso + - youngnick + - mlavacca +references: + - https://github.com/kubernetes-sigs/gateway-api/pull/3477 + - https://github.com/kubernetes-sigs/gateway-api/pull/3213 + - https://github.com/kubernetes-sigs/gateway-api/pull/3632 + - https://github.com/kubernetes-sigs/gateway-api/pull/3664 + - https://github.com/kubernetes-sigs/gateway-api/pull/3587 + - https://github.com/kubernetes-sigs/gateway-api/pull/3588 + - https://github.com/kubernetes-sigs/gateway-api/pull/3682 diff --git a/site-src/ko/geps/gep-1731/index.md b/site-src/ko/geps/gep-1731/index.md new file mode 100644 index 0000000000..acd889e26e --- /dev/null +++ b/site-src/ko/geps/gep-1731/index.md @@ -0,0 +1,444 @@ +# GEP-1731: HTTPRoute Retries + +* Issue: [#1731](https://github.com/kubernetes-sigs/gateway-api/issues/1731) +* Status: Experimental + +(See [status definitions](../overview.md#gep-states).) + +## TLDR + +To allow configuration of a Gateway to retry unsuccessful requests to backends before sending a response to a client request. + +## Goals + +* To allow specification of [HTTP status codes](https://www.rfc-editor.org/rfc/rfc9110#name-overview-of-status-codes) for which a request should be retried. +* To allow specification of the maximum number of times to retry a request. +* To allow specification of the minimum backoff interval between retry attempts. +* To define any interaction with configured HTTPRoute [timeouts](../gep-1742/index.md). +* Retry configuration must be applicable to most known Gateway API implementations. + +## Future Goals + +* To allow specification of a retry ["budget"](https://finagle.github.io/blog/2016/02/08/retry-budgets/) to determine whether a request should be retried, and any shared configuration or interaction with max count retry configuration. +* Define more precise semantics for retry configuration on "consumer" vs "producer" routes for mesh implementations. + +## Non-Goals + +* To allow more granular control of the backoff strategy than many dataplanes allow customizing, such as whether to use an exponential backoff interval between retry attempts, add jitter, or cap the backoff interval to a maximum duration. +* To allow specification of a default retry policy for all routes in a given namespace or attached to a particular Gateway. +* A standard API for approaches for retry logic other than max count or "budget", such as interaction with rate limiting headers. +* To allow specification of gRPC status codes for which a request should be retried (this should be covered in a separate GEP). +* Support for streaming or bidirectional APIs (these could be covered by a future GEP). + +## Introduction + +A Gateway API implementation should be able to retry failed HTTP requests to backends before delivering a response to a client for several reasons: + +* Network Reliability: Networks can be unreliable, and connections might drop or time out. Retrying requests helps ensure that temporary issues don’t prevent the request from being completed. +* Load Balancing: If a server is temporarily overloaded or down, an implementation can retry the request to another server in a load-balanced environment. +* Error Handling: Some HTTP errors, like 500 Internal Server Error or 503 Service Unavailable, might be transient. Retrying the request can help bypass these temporary issues. + +A primary audience for retries in Gateway API configuration are application developers (Ana) who want to ensure their applications are highly available and resilient. These users are best equipped to write sensible configuration, knowing which responses from their application should be retried and tolerances for timeouts and retry attempts to avoid overwhelming their applications with a ["retry storm"](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/retry-storm/) which can cause performance issues, instability or outages. + +Several Gateway API dataplanes support configuring retry semantics using their own bespoke configuration, but the details of these implementations and their user-facing configuration lack consistency between vendors. This proposal is an attempt to reconcile a minimal commonly implementable (and sufficiently useful) API from these divergent existing implementations. + +### Background on implementations + +Most implementations that handle HTTPRoute objects use a proxy as the data plane +implementation, which forwards traffic flows as directed by Gateway API configuration. + +The following table is a review of all the listed implementations of Gateway API +at the time of writing, with the data plane they use for Layer 7, based on what information +could be found online. If there are errors here, or if the implementation doesn't +support Layer 7, please feel free to correct them. + +| Implementation | Data Plane | +|------------------------------------------|------------------| +| Acnodal EPIC | Envoy | +| Apache APISIX | NGINX | +| Azure Application Gateway for Containers | Envoy | +| BIG-IP Kubernetes Gateway | F5 BIG-IP | +| Cilium | Envoy | +| Contour | Envoy | +| Emissary Ingress | Envoy | +| Envoy Gateway | Envoy | +| Flomesh Service Mesh | Pipy | +| Gloo Edge | Envoy | +| Google Kubernetes Engine (GKE) | Similar to Envoy | +| HAProxy Ingress | HAProxy | +| Hashicorp Consul | Envoy | +| Istio | Envoy | +| Kong | NGINX | +| Kuma | Envoy | +| Linkerd | linkerd2-proxy | +| Litespeed | Litespeed WebADC | +| NGINX Gateway Fabric | NGINX | +| Traefik | Traefik | +| VMWare Avi Load Balancer | ? | + +Implementation retry configuration details below have been summarized or copied verbatim from corresponding project documentation, with links to the original source where applicable. + +#### Envoy + +Retries are configurable in a [`RetryPolicy`](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-retrypolicy) set on a [virtual host](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-virtualhost-retry-policy) (roughly equivalent to Listener), the [route](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-routeaction-retry-policy) (equivalent to HTTPRoute), or by setting [Router filter headers](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter). Policies are not merged - the most internal (specific) one becomes the enforced policy. + +By default, Envoy uses a fully jittered exponential back-off algorithm for retries with a default base interval of 25ms, capped at a maximum interval, which defaults to 10 times the base interval (250ms). Explained in more depth in [`x-envoy-max-retries`](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-max-retries). + +* `retry_on` Allows specifying conditions for which a request will be retried, shared types with the header values documented in [x-envoy-retry-on](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#config-http-filters-router-x-envoy-retry-on). + + * [**HTTP**](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-retry-on) + + * `5xx` Retry when the backend returns any 5xx response code. Will not retry if a configured total outer request timeout has been exceeded. + + * `gateway-error` Will retry on 502, 503 and 504 response codes. + + * `reset` Retry if the server does not respond at all (disconnect, reset, timeout). + + * `reset-before-request` Retry if the server does not respond, but only if headers have not been sent yet. + + * `connect-failure` Retry on TCP connection failure, included in `5xx`. + + * `envoy-ratelimited` Retry even if the Envoy is trying to rate limit the connection. + + * `retriable-4xx` Currently includes only 409, with a warning that 409 status codes may indicate a condition which will consistently fail if retried. + + * `refused-stream` Retry if the server resets a stream with a `REFUSED_STREAM` error code, included in `5xx`. + + * `retriable-status-codes` Allows specifying any response code. + + * `retriable-headers` Allows specifying headers in the response for which a request should be retried. + + * `http3-post-connect-failure` Retry if a request is sent over HTTP/3 to the upstream server and fails after connecting. + +* `num_retries` The allowed number of retries, defaults to 1. Further notes on specific behavior can be found under [`x-envoy-max-retries`](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-max-retries). + +* `per_try_timeout` Specifies a non-zero upstream timeout per retry attempt (including the initial attempt). If left unspecified, Envoy will use the global route timeout for the request. Equivalent to the Gateway API HTTPRouteRule BackendRequest timeout. + +* `per_try_idle_timeout` This timeout is useful in cases in which total request timeout is bounded by a number of retries and a per_try_timeout, but there is a desire to ensure each try is making incremental progress. + +* ...several options for retry priority and host selection, likely not portable + +* `retriable_status_codes` Allows specifying any response code for which a request should be retried. + +* `retry_back_off` Allows specifying a default base interval and max interval for retry attempts. + +* `rate_limited_retry_back_off` Advanced configuration for adjusting retry attempt timing based on headers sent in the upstream server response. Alternative to the default exponential back off strategy. + +* `retriable_headers` HTTP response headers for which a backend request should be retried. + +* `retriable_request_headers` HTTP headers which must be present in the _request_ for retries to be attempted. + +Supports configuring a [RetryBudget](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/circuit_breaker.proto#envoy-v3-api-msg-config-cluster-v3-circuitbreakers-thresholds-retrybudget) with a following parameters in cluster CircuitBreaker thresholds. + +* `budget_percent` Specifies the limit on concurrent retries as a percentage of the sum of active requests and active pending requests. For example, if there are 100 active requests and the budget_percent is set to 25, there may be 25 active retries. This parameter is optional. Defaults to 20%. + +* `min_retry_concurrency` Specifies the minimum retry concurrency allowed for the retry budget. The limit on the number of active retries may never go below this number. This parameter is optional. Defaults to 3. + +#### NGINX + +The [`proxy_next_upstream`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream) directive specifies in which cases a request should be passed to the next server: + +* `error` An error occurred while establishing a connection with the server, passing a request to it, or reading the response header. +* `timeout` A timeout has occurred while establishing a connection with the server, passing a request to it, or reading the response header. +* `invalid_header` A server returned an empty or invalid response. +* `http_500` +* `http_502` +* `http_503` +* `http_504` +* `http_403` +* `http_404` +* `http_429` +* `non_idempotent` Normally, requests with a non-idempotent method (POST, LOCK, PATCH) are not passed to the next server if a request has been sent to an upstream server; enabling this option explicitly allows retrying such requests. +* `off` Disables passing a request to the next server. + +Passing a request to the next server is only possible if nothing has been sent to a client yet. That is, if an error or timeout occurs in the middle of the transferring of a response, fixing this is impossible. + +The directive also defines what is considered an unsuccessful attempt of communication with a server. The cases of error, timeout and invalid_header are always considered unsuccessful attempts, even if they are not specified in the directive. The cases of http_500, http_502, http_503, http_504, and http_429 are considered unsuccessful attempts only if they are specified in the directive. The cases of http_403 and http_404 are never considered unsuccessful attempts. + +Passing a request to the next server can be limited by the number of tries and by time. + +* `proxy_next_upstream_timeout time` Limits the time during which a request can be passed to the next server. The 0 value turns off this limitation. Equivalent to the Gateway API BackendRequest timeout. +* `proxy_next_upstream_tries number` Limits the number of possible tries for passing a request to the next server. The 0 value turns off this limitation. + +The `max_fails` and `fail_timeout` parameters in the [`server`](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server) block of an [`upstream`]() module may also interact with retry logic. + +* `max_fails=number` Sets the number of unsuccessful attempts to communicate with the server that should happen in the duration set by the `fail_timeout` parameter to consider the server unavailable for a duration also set by the `fail_timeout` parameter. By default, the number of unsuccessful attempts is set to 1. The zero value disables the accounting of attempts. What is considered an unsuccessful attempt is defined by the proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream, memcached_next_upstream, and grpc_next_upstream directives. + +* `fail_timeout=time` Sets the time during which the specified number of unsuccessful attempts to communicate with the server should happen to consider the server unavailable; and the period of time the server will be considered unavailable. By default, the parameter is set to 10 seconds. Equivalent to Gateway API Request timeout. + +May be possible to implement more advanced logic through Lua scripting or NGINX JavaScript. + +#### HAProxy + +Retry logic can be configured through the [`retry_on`](https://docs.haproxy.org/3.0/configuration.html#4.2-retry-on) and [`retries`](https://docs.haproxy.org/3.0/configuration.html#4.2-retries) proxy settings. + +Using the `retry_on` directive replaces any previous settings with the new ones; it is not cumulative. + +Using anything other than "none" and "conn-failure" allocates a buffer and copies the whole request into it, so it has memory and performance impacts. Requests not fitting in a single buffer will never be +retried.bufsize setting). + +Warns that only requests known to be safe or idempotent requests, such as those with a unique transaction ID header to protect against accidental replays, should be retried. + +* `none` never retry + +* `conn-failure` Retry when the connection or the SSL handshake failed and the request could not be sent. This is the default. + +* `empty-response` Retry when the server connection was closed after part of the request was sent, and nothing was received from the server. This type of failure may be caused by the request timeout on the server side, poor network condition, or a server crash or restart while processing the request. + +* `junk-response` Retry when the server returned something not looking +like a complete HTTP response. This includes partial responses headers as well as non-HTTP contents. It usually is a bad idea to retry on such events, which may be caused a configuration issue (wrong server port) +or by the request being harmful to the server (buffer overflow attack for example). + +* `response-timeout` The server timeout stroke while waiting for the server to respond to the request. This may be caused by poor network condition, the reuse of an idle connection which has expired on the path, or by the request being extremely expensive to process. It generally is a bad idea to retry on such events on servers dealing with heavy database processing (full scans, etc) as it may amplify denial of service attacks. + +* `0rtt-rejected` Retry requests which were sent over early data and were +rejected by the server. These requests are generally considered to be safe to retry. + +* Retry on select HTTP status codes among "401" (Unauthorized), "403" (Forbidden), "404" (Not Found), "408" (Request Timeout), "425" (Too Early), "500" (Server Error), "501" (Not Implemented), "502" (Bad Gateway), "503" (Service Unavailable), "504" (Gateway Timeout). + +* `all-retryable-errors` Retry request for any error that are considered +retryable. This currently activates "conn-failure", "empty-response", "junk-response", "response-timeout", "0rtt-rejected", "500", "502", "503", and "504". + +The [`option redispatch`](https://docs.haproxy.org/3.0/configuration.html#4.2-option%20redispatch) configuration can be used to distribute retries across multiple backend servers, allowing the proxy to break cookie or consistent hash based persistence and redistribute them to a working server. + +#### Traefik + +Offers a [Retry middleware](https://doc.traefik.io/traefik/middlewares/http/retry/) allowing configuration of number of attempts and initial interval. + +Reissues requests a given number of times to a backend server if that server does not reply. As soon as the server answers, the middleware stops retrying, _regardless of the response status_. Has an optional configuration to enable an exponential backoff. + +* `attempts` Defines how many times the request should be retried. + +* `initialInterval` Defines the first wait time in the backoff series. The maximum interval is calculated as twice the `initialInterval`. If unspecified, requests will be retried immediately. The value should be provided in seconds or as a valid duration format. + +Supports configuration of a [Circuit Breaker](https://doc.traefik.io/traefik/middlewares/http/circuitbreaker/) which could possibly be used to implement budgeted retries. Each router gets its own instance of a given circuit breaker. One circuit breaker instance can be open while the other remains closed: their state is not shared. This is the expected behavior, we want you to be able to define what makes a service healthy without having to declare a circuit breaker for each route. + +#### linkerd2-proxy + +Linkerd supports [budgeted retries](https://linkerd.io/2.15/features/retries-and-timeouts/) and - as of [edge-24.7.5](https://github.com/linkerd/linkerd2/releases/tag/edge-24.7.5) - counted retries. In all cases, retries are implemented by the `linkerd2-proxy` making the request on behalf on an application workload. + +Linkerd's budgeted retries allow retrying an indefinite number of times, as long as the fraction of retries remains within the budget. Budgeted retries are supported only using Linkerd's native ServiceProfile CRD, which allows enabling retries, setting the retry budget (by default, 20% plus 10 "extra" retries per second), and configuring the window over which the fraction of retries to non-retries is calculated. + +Linkerd's counted retries work in much the same way as other retry implementations, permitted a fixed maximum number of retries for a given request. Counted retries can be configured with annotations on Service, HTTPRoute, and GRPCRoute resources, all of which allow setting the maximum number of retries and the maximum time a request will be permitted to linger before cancelling it and retrying. + +For Service and HTTPRoute, Linkerd permits setting which HTTP statuses will be retried. For Service and GRPCRoute, Linkerd permits setting which gRPC statuses will be retried. Retry configurations on HTTPRoute and GRPCRoute resources take precedence over retry configurations on Service resources. + +Neither type of Linkerd retries supports configuring retries based on connection status (e.g. connection timed out). The `linkerd2-proxy` maintains long-lived connections to destinations in use, and manages connection state independently of the application making requests. In this world, individual requests don't correlate well with connections being made or broken, which means that retries on connection state changes don't really make sense. + +#### F5 BIG-IP + +TODO + +#### Pipy + +TODO + +#### Litespeed WebADC + +TODO + +## API + +!!! warning + Expectations for how implementations should handle connection errors are currently UNRESOLVED due to inconsistency between data planes, including how connections are established or maintained, granularity of how different types of errors are bucketed, default behavior and expected user needs. Please see comment thread at for more detail. + +### Go + +```golang +type HTTPRouteRule struct { + // Retry defines the configuration for when to retry an HTTP request. + // + // Support: Extended + // + // +optional + // + Retry *HTTPRouteRetry `json:"retry,omitempty"` + + // ... +} + +// HTTPRouteRetry defines retry configuration for an HTTPRoute. +// +// Implementations SHOULD retry on connection errors (disconnect, reset, timeout, +// TCP failure) if a retry stanza is configured. +// +type HTTPRouteRetry struct { + // Codes defines the HTTP response status codes for which a backend request + // should be retried. + // + // Support: Extended + // + // +optional + // + Codes []HTTPRouteRetryStatusCode `json:"codes,omitempty"` + + // Attempts specifies the maximum number of times an individual request + // from the gateway to a backend should be retried. + // + // If the maximum number of retries has been attempted without a successful + // response from the backend, the Gateway MUST return an error. + // + // When this field is unspecified, the number of times to attempt to retry + // a backend request is implementation-specific. + // + // Support: Extended + // + // +optional + Attempts *Int `json:"attempts,omitempty"` + + // Backoff specifies the minimum duration a Gateway should wait between + // retry attempts and is represented in Gateway API Duration formatting. + // + // For example, setting the `rules[].retry.backoff` field to the value + // `100ms` will cause a backend request to first be retried approximately + // 100 milliseconds after timing out or receiving a response code configured + // to be retryable. + // + // An implementation MAY use an exponential or alternative backoff strategy + // for subsequent retry attempts, MAY cap the maximum backoff duration to + // some amount greater than the specified minimum, and MAY add arbitrary + // jitter to stagger requests, as long as unsuccessful backend requests are + // not retried before the configured minimum duration. + // + // If a Request timeout (`rules[].timeouts.request`) is configured on the + // route, the entire duration of the initial request and any retry attempts + // MUST not exceed the Request timeout duration. If any retry attempts are + // still in progress when the Request timeout duration has been reached, + // these SHOULD be canceled if possible and the Gateway MUST immediately + // return a timeout error. + // + // If a BackendRequest timeout (`rules[].timeouts.backendRequest`) is + // configured on the route, any retry attempts which reach the configured + // BackendRequest timeout duration without a response SHOULD be canceled if + // possible and the Gateway should wait for at least the specified backoff + // duration before attempting to retry the backend request again. + // + // If a BackendRequest timeout is _not_ configured on the route, retry + // attempts MAY time out after an implementation default duration, or MAY + // remain pending until a configured Request timeout or implementation + // default duration for total request time is reached. + // + // When this field is unspecified, the time to wait between retry attempts + // is implementation-specific. + // + // Support: Extended + // + // +optional + Backoff *Duration `json:"backoff,omitempty"` +} + +// HTTPRouteRetryStatusCode defines an HTTP response status code for +// which a backend request should be retried. +// +// Implementations MUST support the following status codes as retryable: +// +// * 500 +// * 502 +// * 503 +// * 504 +// +// Implementations MAY support specifying additional discrete values in the +// 500-599 range. +// +// Implementations SHOULD NOT support retrying status codes in the 100-399 +// range, as these responses are generally not appropriate to retry. +// +// Implementations MAY support specifying discrete values in the 400-499 range, +// which are often inadvisable to retry. +// +// Implementations MAY support discrete values in the 600-999 (inclusive) +// range, which are not valid for HTTP clients, but are sometimes used for +// communicating application-specific errors. +// +// +kubebuilder:validation:Minimum:=100 +// +kubebuilder:validation:Maximum:=999 +type HTTPRouteRetryStatusCode int + +// Duration is a string value representing a duration in time. The format is +// as specified in GEP-2257, a strict subset of the syntax parsed by Golang +// time.ParseDuration. +// +// +kubebuilder:validation:Pattern=`^([0-9]{1,5}(h|m|s|ms)){1,4}$` +type Duration string +``` + +### YAML + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: retry-example +spec: + ... + rules: + - backendRefs: + - name: some-service + port: 8080 + retry: + codes: + - 500 + - 502 + - 503 + - 504 + attempts: 2 + backoff: 100ms +``` + +## Conformance Details + +Basic support for configuring retries in HTTPRoute up to a specified maximum count and with a minimum duration between attempts will be gated on the `SupportHTTPRouteRetry` feature. Retries will be tested in combination with request and backend timeouts if supported by the implementation. + +Retrying requests based on HTTP status codes will be gated under the following features: + +* `SupportHTTPRouteRetryBackendTimeout` + + * Will test that backend requests that exceed a BackendRequest timeout duration are retried if a `retry` stanza is configured. + +* `SupportHTTPRouteRetryBackoff` + + * Backoff will only be tested that a retry does not start before the duration specified for conformance, not that the backoff duration is precise. + * Not currently supportable by NGINX or HAProxy. + +* `SupportHTTPRouteRetryCodes` + + * Only 500, 502, 503 and 504 will be tested for conformance. + * Traefik does not seem to support specifying error codes, and will only retry on backend timeouts. + +* `SupportHTTPRouteRetryConnectionError` + + * Will test that connections interrupted by a TCP failure, disconnect or reset are retried if a `retry` stanza is configured. + +## Alternatives + +### Standard RetryPolicy metaresource + +This may be a reasonable approach for configuring broad default retry policies, but the UX of using a separate resource could feel overly burdensome for basic use cases or granular configuration, and the structure of the policy attachment model is [currently being revised](https://github.com/kubernetes-sigs/gateway-api/discussions/2927). Additionally, multiple data plane proxies warn in their documentation about the danger of configuring broad retry policies which may cause logical application errors from replaying non-idempotent requests or overwhelm backends. This approach may still be considered to enable future goals. + +### HTTPRoute filter + +Implementing a `requestRetryPolicy` [HTTPRouteFilter](../../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteFilter) type is likely a reasonable alternative implementation (with the downside of slightly deeping nesting and more complex structural configuration) that was not fully explored. + +Adding a new field to HTTPRouteRule instead is proposed for parity with the similar and intersecting configuration of [HTTPRouteTimeouts](../../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteTimeouts). + +## Other considerations + +### What accommodations are needed for future retry budget support? + +Changing the retry stanza to a Kubernetes "tagged union" pattern with something like `mode: "budget"` to support mutually-exclusive distinct sibling fields is possible as a non-breaking change if omitting the `mode` field defaults to the currently proposed behavior (which could retroactively become something like `mode: count`). + +### Should whether to retry on connection errors be configurable? + +Retrying on connection errors (disconnect, reset, timeout, TCP failure) is typically default behavior for most dataplanes, even those that don't support configurable retries based on HTTP status codes. Some proxies allow this to be configurable, but retrying attempts on these sort of errors is typically desirable and excluding it from the Gateway API spec both allows a simpler UX with less boilerplate, and avoids nuances between how these are defined and configured in different proxies. + +### Should whether to retry on a backend timeout be configurable? + +On Kubernetes, retrying should _typically_ route a backend request to a different pod if the original destination has become unhealthy and therefore should generally be safe. Even if a [BackendLBPolicy](../gep-1619/index.md) is configured, most dataplane implementations implement "soft" affinity rather than strict session routing. The warnings against this practice in NGINX and HAProxy documentation seem to reference risks with legacy deployment models using a small number of statically-defined servers. We could consider adding something like a `excludeRetryOnTimeout` boolean field (implementable by NGINX and HAProxy, not by Envoy) in the future if this behavior is desirable, while still retaining the retry-on-timeout behavior as a default. + +## References + +* +* +* +* +* diff --git a/site-src/ko/geps/gep-1731/metadata.yaml b/site-src/ko/geps/gep-1731/metadata.yaml new file mode 100644 index 0000000000..c85ccbcb0c --- /dev/null +++ b/site-src/ko/geps/gep-1731/metadata.yaml @@ -0,0 +1,47 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1731 +name: HTTPRoute Retries +status: Experimental +# Any authors who contribute to the GEP in any way should be listed here using +# their GitHub handle. +authors: + - mikemorris +relationships: + # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely + # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field + # set back to this GEP, and MUST be moved to Declined. + obsoletes: {} + obsoletedBy: {} + # extends indicates that a GEP extends the linked GEP, adding more detail + # or additional implementation. The extended GEP MUST have its extendedBy + # field set back to this GEP. + extends: {} + extendedBy: + - number: 3388 + name: Retry Budgets + # seeAlso indicates other GEPs that are relevant in some way without being + # covered by an existing relationship. + seeAlso: + - number: 2257 + name: Gateway API Duration Format + description: Uses duration format introduced in this GEP. + - number: 1742 + name: HTTPRoute Timeouts + description: Covers some overlapping considerations around when requests should be retried. +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: + - https://www.rfc-editor.org/rfc/rfc9110 + - https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml +# featureNames is a list of the feature names introduced by the GEP, if there +# are any. This will allow us to track which feature was introduced by which GEP. +featureNames: + - SupportHTTPRouteRetry + - SupportHTTPRouteRetryBackendTimeout + - SupportHTTPRouteRetryBackoff + - SupportHTTPRouteRetryCodes + - SupportHTTPRouteRetryConnectionError +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: {} diff --git a/site-src/ko/geps/gep-1742/index.md b/site-src/ko/geps/gep-1742/index.md new file mode 100644 index 0000000000..ad58405ed3 --- /dev/null +++ b/site-src/ko/geps/gep-1742/index.md @@ -0,0 +1,509 @@ +# GEP-1742: HTTPRoute Timeouts + +* Issue: [#1742](https://github.com/kubernetes-sigs/gateway-api/issues/1742) +* Status: Standard + +(See [status definitions](../overview.md#gep-states).) + +## TLDR + +Create some sort of design so that Gateway API objects can be used to configure +timeouts for different types of connection. + +## Goals + +- Create some method to configure some timeouts. +- Timeout config must be applicable to most if not all Gateway API implementations. + +## Non-Goals + +- A standard API for every possible timeout that implementations may support. + +## Introduction + +In talking about Gateway API objects, particularly HTTPRoute, we've mentioned +timeout configuration many times in the past as "too hard" to find the common +ground necessary to make more generic configuration. This GEP intends firstly +to make this process less difficult, then to find common timeouts that we can +build into Gateway API. + +For this initial round, we'll focus on Layer 7 HTTP traffic, while acknowledging +that Layer 4 connections have their own interesting timeouts as well. + +The following sections will review all the implementations, then document what +timeouts are _available_ for the various data planes. + +### Background on implementations + +Most implementations that handle HTTPRoute objects use a proxy as the data plane +implementation, that actually forwards flows as directed by Gateway API configuration. + +The following table is a review of all the listed implementations of Gateway API +at the time of writing, with the data plane they use for Layer 7, based on what information +could be found online. If there are errors here, or if the implementation doesn't +support layer 7, please feel free to correct them. + +| Implementation | Data Plane | +|----------------|------------| +| Acnodal EPIC | Envoy | +| Apache APISIX | Nginx | +| BIG-IP Kubernetes Gateway| F5 BIG-IP | +| Cilium | Envoy | +| Contour | Envoy | +| Emissary Ingress| Envoy | +| Envoy Gateway | Envoy | +| Flomesh Service Mesh | Pipy | +| Gloo Edge | Envoy | +| Google Kubernetes Engine (GKE) | Similar to Envoy Timeouts | +| HAProxy Ingress | HAProxy | +| Hashicorp Consul | Envoy | +| Istio | Envoy | +| Kong | Nginx | +| Kuma | Envoy | +| Litespeed | Litespeed WebADC | +| NGINX Gateway Fabric | Nginx | +| Traefik | Traefik | + + +### Flow diagrams with available timeouts + +The following flow diagrams are based off the basic diagram below, with all the +timeouts I could find included. + +In general, timeouts are recorded with the setting name or similar that the data +plane uses for them, and are correct as far as I've parsed the documentation +correctly. + +Idle timeouts are marked as such. + +```mermaid +sequenceDiagram + participant C as Client + participant P as Proxy + participant U as Upstream + C->>P: Connection Started + C->>P: Starts sending Request + C->>P: Finishes Headers + C->>P: Finishes request + P->>U: Connection Started + P->>U: Starts sending Request + P->>U: Finishes request + P->>U: Finishes Headers + U->>P: Starts Response + U->>P: Finishes Headers + U->>P: Finishes Response + P->>C: Starts Response + P->>C: Finishes Headers + P->>C: Finishes Response + Note right of P: Repeat if connection sharing + U->>C: Connection ended +``` + +#### Envoy Timeouts + +For Envoy, some timeouts are configurable at either the HTTP Connection Manager +(very, very roughly equivalent to a Listener), the Route (equivalent to a HTTPRoute) +level, or the Cluster (usually close to the Service) or some combination. These +are noted in the below diagram with a `CM`, `R`, or `Cluster` prefix respectively. + +```mermaid +sequenceDiagram + participant C as Client + participant P as Envoy + participant U as Upstream + C->>P: Connection Started + activate P + Note left of P: transport_socket_connect_timeout for TLS + deactivate P + C->>P: Starts sending Request + activate C + activate P + activate P + C->>P: Finishes Headers + note left of P: CM request_headers_timeout + C->>P: Finishes request + deactivate P + activate U + note left of U: Cluster connect_timeout + deactivate U + P->>U: Connection Started + activate U + note right of U: CM idle_timeout
CM max_connection_duration + P->>U: Starts sending Request + P->>U: Finishes Headers + note left of P: CM request_timeout + P->>U: Finishes request + deactivate P + activate U + U->>P: Starts Response + U->>P: Finishes Headers + note right of U: R timeout
R per_try_timeout
R per_try_idle_timeout + U->>P: Finishes Response + deactivate U + P->>C: Starts Response + P->>C: Finishes Headers + P->>C: Finishes Response + Note left of C: CM stream_idle_timeout
R idle_timeout
CM,R max_stream_duration
TCP proxy idle_timeout
TCP protocol idle_timeout + deactivate C + Note right of P: Repeat if connection sharing + U->>C: Connection ended + deactivate U +``` + +#### Nginx timeouts + +Nginx allows setting of GRPC and general HTTP timeouts separately, although the +purposes seem to be roughly equivalent. + +```mermaid +sequenceDiagram + participant C as Client + participant P as Nginx + participant U as Upstream + C->>P: Connection Started + activate P + C->>P: Starts sending Request + C->>P: Finishes Headers + Note right of P: client_headers_timeout + deactivate P + activate P + C->>P: Finishes request + deactivate P + Note right of P: client_body_timeout + activate U + note left of U: proxy_connect_timeout
grpc_connect_timeout + deactivate U + P->>U: Connection Started + Activate U + Activate U + P->>U: Starts sending Request + P->>U: Finishes Headers + P->>U: Finishes request + Note right of U: (between write operations)
proxy_send_timeout
grpc_send_timeout + deactivate U + activate U + U->>P: Starts Response + U->>P: Finishes Headers + Note right of U: (between read operations)
proxy_read_timeout
grpc_read_timeout + U->>P: Finishes Response + deactivate U + activate P + P->>C: Starts Response + P->>C: Finishes Headers + P->>C: Finishes Response + deactivate P + Note left of P: send_timeout (only between two successive write operations) + Note left of C: Repeat if connection is shared until server's keepalive_timeout is hit + Note Right of U: upstream's keepalive_timeout (if keepalive enabled) + U->>C: Connection ended + deactivate U +``` + +#### HAProxy timeouts + +```mermaid +sequenceDiagram + participant C as Client + participant P as Proxy + participant U as Upstream + + C->>P: Connection Started + activate U + activate C + activate P + note left of P: timeout client (idle) + C->>P: Starts sending Request + C->>P: Finishes Headers + C->>P: Finishes request + note left of C: timeout http-request + deactivate C + activate C + note left of C: timeout client-fin + deactivate C + deactivate P + activate U + note left of U: timeout queue
(wait for available server) + deactivate U + + P->>U: Connection Started + activate U + P->>U: Starts sending Request + activate U + P->>U: Finishes Headers + P->>U: Finishes request + + note right of U: timeout connect + deactivate U + note left of U: timeout server
(idle timeout) + deactivate U + activate U + note left of U: timeout server-fin + deactivate U + U->>P: Starts Response + U->>P: Finishes Headers + U->>P: Finishes Response + P->>C: Starts Response + P->>C: Finishes Headers + P->>C: Finishes Response + activate C + note left of C: timeout http-keep-alive + deactivate C + Note right of P: Repeat if connection sharing + Note right of U: timeout tunnel
(for upgraded connections) + deactivate U + U->>C: Connection ended + +``` + +#### Traefik timeouts + +```mermaid +sequenceDiagram + participant C as Client + participant P as Proxy + participant U as Upstream + C->>P: Connection Started + activate U + C->>P: Starts sending Request + activate P + C->>P: Finishes Headers + Note right of P: respondingTimeouts
readTimeout + C->>P: Finishes request + deactivate P + P->>U: Connection Started + activate U + Note right of U: forwardingTimeouts
dialTimeout + deactivate U + P->>U: Starts sending Request + P->>U: Finishes request + P->>U: Finishes Headers + U->>P: Starts Response + activate U + note right of U: forwardingTimeouts
responseHeaderTimeout + U->>P: Finishes Headers + deactivate U + U->>P: Finishes Response + P->>C: Starts Response + activate P + P->>C: Finishes Headers + Note right of P: respondingTimeouts
writeTimeout + P->>C: Finishes Response + deactivate P + Note right of P: Repeat if connection sharing + Note right of U: respondingTimeouts
idleTimeout
Keepalive connections only + deactivate U + U->>C: Connection ended + +``` +#### F5 BIG-IP Timeouts + +Could not find any HTTP specific timeouts. PRs welcomed. 😊 + +#### Pipy Timeouts + +Could not find any HTTP specific timeouts. PRs welcomed. 😊 + +#### Litespeed WebADC Timeouts + +Could not find any HTTP specific timeouts. PRs welcomed. 😊 + +## API + +The above diagrams show that there are many different kinds of configurable timeouts +supported by Gateway implementations: connect, idle, request, upstream, downstream. +Although there may be opportunity for the specification of a common API for more of +them in the future, this GEP will focus on the L7 timeouts in HTTPRoutes that are +most valuable to clients. + +From the above analysis, it appears that most implementations are capable of +supporting the configuration of simple client downstream request timeouts on HTTPRoute +rules. This is a relatively small addition that would benefit many users. + +Some implementations support configuring a timeout for individual backend requests, +separate from the overall client request timeout. This is particularly useful if a +client HTTP request to a gateway can result in more than one call from the gateway +to the destination backend service, for example, if automatic retries are supported. +Adding support for this would also benefit many users. + +### Timeout values + +There are 2 kinds of timeouts that can be configured in an `HTTPRouteRule`: + +1. `timeouts.request` is the timeout for the Gateway API implementation to send a + response to a client HTTP request. Whether the gateway starts the timeout before + or after the entire client request stream has been received, is implementation dependent. + This field is optional `Extended` support. + +1. `timeouts.backendRequest` is a timeout for a single request from the gateway to a backend. + This field is optional `Extended` support. Typically used in conjunction with retry configuration, + if supported by an implementation. + Note that retry configuration will be the subject of a separate GEP (GEP-1731). + +```mermaid +sequenceDiagram + participant C as Client + participant P as Proxy + participant U as Upstream + C->>P: Connection Started + note left of P: timeouts.request start time (min) + C->>P: Starts sending Request + C->>P: Finishes Headers + C->>P: Finishes request + note left of P: timeouts.request start time (max) + P->>U: Connection Started + note right of P: timeouts.backendRequest start time + P->>U: Starts sending Request + P->>U: Finishes request + P->>U: Finishes Headers + U->>P: Starts Response + U->>P: Finishes Headers + note right of P: timeouts.backendRequest end time + note left of P: timeouts.request end time + U->>P: Finishes Response + note right of P: Repeat if retry + P->>C: Starts Response + P->>C: Finishes Headers + P->>C: Finishes Response + Note right of P: Repeat if connection sharing + U->>C: Connection ended +``` + +Both timeout fields are [GEP-2257 Duration] values. A zero-valued timeout +("0s") MUST be interpreted as disabling the timeout; a non-zero-valued timeout +MUST be >= 1ms. + +[GEP-2257 Duration]:../gep-2257/index.md + +### GO + +```go +type HTTPRouteRule struct { + // Timeouts defines the timeouts that can be configured for an HTTP request. + // + // Support: Extended + // + // +optional + // + Timeouts *HTTPRouteTimeouts `json:"timeouts,omitempty"` + + // ... +} + +// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute. +// Timeout values are represented with Gateway API Duration formatting. +// Specifying a zero value such as "0s" is interpreted as no timeout. +// +// +kubebuilder:validation:XValidation:message="backendRequest timeout cannot be longer than request timeout",rule="!(has(self.request) && has(self.backendRequest) && duration(self.request) != duration('0s') && duration(self.backendRequest) > duration(self.request))" +type HTTPRouteTimeouts struct { + // Request specifies the maximum duration for a gateway to respond to an HTTP request. + // If the gateway has not been able to respond before this deadline is met, the gateway + // MUST return a timeout error. + // + // For example, setting the `rules.timeouts.request` field to the value `10s` in an + // `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds + // to complete. + // + // This timeout is intended to cover as close to the whole request-response transaction + // as possible although an implementation MAY choose to start the timeout after the entire + // request stream has been received instead of immediately after the transaction is + // initiated by the client. + // + // The value of Request is a Gateway API Duration string as defined by GEP-2257. When this + // field is unspecified, request timeout behavior is implementation-specific. + // + // Support: Extended + // + // +optional + Request *Duration `json:"request,omitempty"` + + // BackendRequest specifies a timeout for an individual request from the gateway + // to a backend. This covers the time from when the request first starts being + // sent from the gateway to when the full response has been received from the backend. + // + // An entire client HTTP transaction with a gateway, covered by the Request timeout, + // may result in more than one call from the gateway to the destination backend, + // for example, if automatic retries are supported. + // + // The value of BackendRequest must be a Gateway API Duration string as defined by + // GEP-2257. When this field is unspecified, its behavior is implementation-specific; + // when specified, the value of BackendRequest must be no more than the value of the + // Request timeout (since the Request timeout encompasses the BackendRequest timeout). + // + // Support: Extended + // + // +optional + BackendRequest *Duration `json:"backendRequest,omitempty"` +} + +// Duration is a string value representing a duration in time. The format is as specified +// in GEP-2257, a strict subset of the syntax parsed by Golang time.ParseDuration. +// +// +kubebuilder:validation:Pattern=`^([0-9]{1,5}(h|m|s|ms)){1,4}$` +type Duration string +``` + +### YAML + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: timeout-example +spec: + ... + rules: + - backendRefs: + - name: some-service + port: 8080 + timeouts: + request: 10s + backendRequest: 2s +``` + +### Conformance Details + +Gateway implementations can indicate support for the optional behavior in this GEP using +the following feature names: + +- `HTTPRouteRequestTimeout`: supports `rules.timeouts.request` in an `HTTPRoute`. +- `HTTPRouteBackendTimeout`: supports `rules.timeouts.backendRequest` in an `HTTPRoute`. + +## Alternatives + +Timeouts could be configured using policy attachments or in objects other than `HTTPRouteRule`. + +### Policy Attachment + +Instead of configuring timeouts directly on an API object, they could be configured using policy +attachments. The advantage to this approach would be that timeout policies can be not only +configured for an `HTTPRouteRule`, but can also be added/overridden at a more fine +(e.g., `HTTPBackendRef`) or coarse (e.g. `HTTPRoute`) level of granularity. + +The downside, however, is complexity introduced for the most common use case, adding a simple +timeout for an HTTP request. Setting a single field in the route rule, instead of needing to +create a policy resource, for this simple case seems much better. + +In the future, we could consider using policy attachments to configure less common kinds of +timeouts that may be needed, but it would probably be better to instead extend the proposed API +to support those timeouts as well. + +The default values of the proposed timeout fields could also be overridden +using policy attachments in the future. For example, a policy attachment could be used to set the +default value of `rules.timeouts.request` for all routes under an `HTTPRoute` or `Gateway`. + +### Other API Objects + +The new timeouts field could be added to a different API struct, instead of `HTTPRouteRule`. + +Putting it on an `HTTPBackendRef`, for example, would allow users to set different timeouts for different +backends. This is a feature that we believe has not been requested by existing proxy or service mesh +clients and is also not implementable using available timeouts of most proxies. + +Another alternative is to move the timeouts configuration up a level in the API to `HTTPRoute`. This +would be convenient when a user wants the same timeout on all rules, but would be overly restrictive. +Using policy attachments to override the default timeout value for all rules, as described in the +previous section, is likely a better way to handle timeout configuration above the route rule level. + +## References + +[GEP-2257]:../gep-2257/index.md diff --git a/site-src/ko/geps/gep-1742/metadata.yaml b/site-src/ko/geps/gep-1742/metadata.yaml new file mode 100644 index 0000000000..de1f0dd26b --- /dev/null +++ b/site-src/ko/geps/gep-1742/metadata.yaml @@ -0,0 +1,24 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1742 +name: HTTPRoute Timeouts +status: Standard +authors: + - youngnick + - spacewander + - frankbu + - shaneutt + - candita + - robscott + - sjberman +relationships: + seeAlso: + - number: 2257 + name: Gateway API Duration Format + description: Defines the duration format used by HTTPRoute timeouts. +references: + - https://datatracker.ietf.org/doc/html/rfc8174 + - https://datatracker.ietf.org/doc/html/rfc2119 +changelog: + - https://github.com/kubernetes-sigs/gateway-api/pull/3210 + diff --git a/site-src/ko/geps/gep-1748/index.md b/site-src/ko/geps/gep-1748/index.md new file mode 100644 index 0000000000..fa1ec20b12 --- /dev/null +++ b/site-src/ko/geps/gep-1748/index.md @@ -0,0 +1,150 @@ +# GEP-1748: Gateway API Interaction with Multi-Cluster Services + +* Issue: [#1748](https://github.com/kubernetes-sigs/gateway-api/issues/1748) +* Status: Experimental + +???+ Prolonged Experimental Phase + This GEP will be in the "Experimental" channel for a prolonged period of + time. This explores the interaction of Gateway API with the Multi-Cluster + Services API. Until the MCS API is also GA, it will be impossible for this + GEP to graduate beyond "Experimental". + + This GEP is also exempt from the [Probationary Period][expprob] rules as it + predated them. + +[expprob]:../overview.md#probationary-period + +## TLDR + +The Kubernetes Multi-Cluster Services API enables Services to span multiple +clusters. Gateway API enables advanced traffic routing, serving as the next +generation Ingress, Load Balancing, and Mesh API. This document describes how +these APIs can be used together. + +## Goals + +* Define the interaction between Gateway API and Multi-Cluster Services +* Define any situations where Gateway API may span multiple clusters without the + Multi-Cluster Services API + +## Non-Goals + +* Make significant changes to either API + +## Introduction + +Gateway API and the Multi-Cluster Services API represent two of the newest +Kubernetes networking APIs. As they’ve been developed in parallel, there’s been +some cross-project discussion about how they can interact, but that has never +formally been written down. This GEP aims to change that. + +## Overview + +Multi-Cluster Services can be used within Gateway API wherever Services can be +used. The difference is that Services refer only to cluster-local endpoints while +Multi-Cluster Services can refer to endpoints throughout an entire ClusterSet. + +### ServiceImport as a Backend + +A Route can forward traffic to the endpoints attached to an imported Service. +This behaves identically to how forwarding to Services work in Kubernetes, with +the exception that the endpoints attached to a ServiceImport may span multiple +clusters. For example, the following HTTPRoute would forward traffic to +endpoints attached to the "store" ServiceImport: + +```yaml +{% include 'standard/multicluster/httproute-simple.yaml' %} +``` + +#### Routing to Specific Clusters + +In some cases, it may be helpful to route certain paths to a specific cluster +(or region). Similar to single-cluster Services, this can be accomplished by +creating multiple Multi-Cluster Services, one for each subset of endpoints you +would like to route to. For example, the following configuration will send +requests with paths prefixed with “/west” to the store-west ServiceImport, and +“/east” to the store-east ServiceImport. Requests that don’t match either of +these paths will be routed to the “store” ServiceImport which represents a +superset of the “store-west” and “store-east” ServiceImports. + +```yaml +{% include 'standard/multicluster/httproute-location.yaml' %} +``` + +#### Advanced Routing With ServiceImports + +All Routing capabilities in Gateway API should apply equally whether the backend +is a Service or ServiceImport. For example, when routing to a system with +multiple read replicas, it could be beneficial to route requests based on HTTP +Method. In the following example, requests with POST, PUT, and DELETE methods +are routed to `api-primary` while the rest are routed to `api-replicas`: + +```yaml +{% include 'standard/multicluster/httproute-method.yaml' %} +``` + +#### Routing to Both Services and ServiceImports + +There are some situations where it will be useful to split traffic between a +Service and ServiceImport. In the following example, 90% of traffic would go to +endpoints attached to the cluster-local "store" Service, and the remaining 10% +would go to endpoints attached to the Multi-Cluster "store-global" Service: + +```yaml +{% include 'standard/multicluster/httproute-hybrid.yaml' %} +``` + +#### Cross-Namespace References with ReferenceGrant + +It is possible to use ReferenceGrant to enable cross-namespace references to +ServiceImports. For example, the following HTTPRoute would forward traffic to +endpoints attached to the “bar” Multi-Cluster Service in the “bar” namespace: + +```yaml +{% include 'standard/multicluster/httproute-referencegrant.yaml' %} +``` + +### Mesh: ServiceImport as Parent + +In some cases, you may want to override traffic destined for a Multi-Cluster +Service with a mesh. As part of the broader GAMMA initiative, ServiceImport can +be used in the same way that Service is used as a ParentRef. When a Service is +specified as a parent, meshes will intercept traffic destined for the ClusterIP +of the Service and apply any policies or routing decisions defined by the Route. +Similarly, when a ServiceImport is specified as a parent, meshes will intercept +traffic destined for the ClusterSetIP and apply any policies or routing +decisions defined by the Route. In the following example, the mesh would +intercept traffic destined for the store ClusterSetIP matching the `/cart` path +and redirect it to the `cart` Multi-Cluster Service. + +```yaml +{% include 'standard/multicluster/httproute-gamma.yaml' %} +``` + +### Services vs ServiceImports + +It is important that all implementations provide a consistent experience. That +means that references to Services SHOULD always be interpreted as references to +endpoints within the same cluster for that Service. References to ServiceImports +MUST be interpreted as routing to Multi-Cluster endpoints across the ClusterSet +for the given ServiceImport. In practice, that means that users should use +“Service” when they want to reference cluster-local endpoints, and +“ServiceImport” when they want to route to Multi-Cluster endpoints across the +ClusterSet for the given ServiceImport. This behavior should be analogous to +using `.cluster.local` versus `.clusterset.local` DNS for a given Service. + +## API Changes + +* ServiceImport is recognized as backend with “Extended” conformance +* ServiceImport is included in GAMMA GEP(s) with “Extended” conformance +* Clarification that Services refer to endpoints within the same cluster + +## Alternatives + +### Develop Custom Multi-Cluster Concepts Independently from Multi-Cluster Services + +We could theoretically develop an entirely new way to handle multi-cluster routing. We’re choosing not to do that because the existing APIs are sound and can work well together. + +## References + +* [Original Doc](https://docs.google.com/document/d/1akwzBKtMKkkUV8tX-O7tPcI4BPMOLZ-gmS7Iz-7AOQE/edit#) diff --git a/site-src/ko/geps/gep-1748/metadata.yaml b/site-src/ko/geps/gep-1748/metadata.yaml new file mode 100644 index 0000000000..5e479c8d01 --- /dev/null +++ b/site-src/ko/geps/gep-1748/metadata.yaml @@ -0,0 +1,7 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1748 +name: Gateway API Interaction with Multi-Cluster Services +status: Experimental +authors: + - robscott diff --git a/site-src/ko/geps/gep-1762/index.md b/site-src/ko/geps/gep-1762/index.md new file mode 100644 index 0000000000..e5f4ebf395 --- /dev/null +++ b/site-src/ko/geps/gep-1762/index.md @@ -0,0 +1,247 @@ +# GEP-1762: In Cluster Gateway Deployments + +* Status: Standard + +## Overview + +Gateway API provides a common abstraction over different implementations, whether they are implemented by cloud load balancers, in-cluster deployments, or other mechanisms. However, many in-cluster implementations have solved some of the same problems in different ways. + +Related discussions: + +* [Support cluster-local Gateways](https://github.com/kubernetes-sigs/gateway-api/discussions/1247) +* [Scaling Gateway Resources](https://github.com/kubernetes-sigs/gateway-api/discussions/1355) +* [Manual deployments](https://github.com/kubernetes-sigs/gateway-api/issues/1687) +* [Merging Gateways](https://github.com/kubernetes-sigs/gateway-api/pull/1863/) +* [Per-Gateway Infrastructure](https://github.com/kubernetes-sigs/gateway-api/pull/1757) + +## Goals + +* Provide prescriptive guidance for how in-cluster implementations should behave. +* Provide requirements for how in-cluster implementations should behave. + +Note that some changes will be suggestions, while others will be requirements. + +## Non-Goals + +* Provide guidance to how out-of-cluster implementations should behave. Rather, this document aims to bring consistency between these types. + +## Terminology + +This document uses a few terms throughout. To ensure consistency, they are defined below: + +* In-cluster deployment: refers to an implementation that actuates a `Gateway` by running a data plane in the cluster. + This is *often*, but not necessarily, by deploying a `Deployment`/`DaemonSet` and `Service`. +* Automated deployment: refers to an implementation that automatically deploys the data plane based on a `Gateway`. + That is, the user simply creates a `Gateway` resource and the rest is handled behind the scenes by the implementation. + +## Design + +This GEP both introduces new API fields, and standardizes how implementations should behave when implementing the existing API. + +### Automated Deployments + +A simple `Gateway`, as is configured below is assumed to be an automated deployment: + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: my-gateway +spec: + gatewayClassName: example + listeners: + - name: default + port: 80 + protocol: HTTP +``` + +With this configuration, an implementation: + +* MUST mark the Gateway as `Programmed` and provide an address in `Status.Addresses` where the Gateway can be reached on each configured port. +* MUST label all generated resources (Service, Deployment, etc) with `gateway.networking.k8s.io/gateway-name: my-gateway` (where `my-gateway` is the name of the Gateway resource). +* MUST provision generated resources in the same namespace as the Gateway if they are namespace scoped resources. + * Cluster scoped resources are not recommended. +* SHOULD name all generated resources `my-gateway-example` (`-`). + This is not simply `NAME` to reduce the chance of conflicts with existing resources. + Where required, this can also serve as the prefix for the object. + +### Customizations + +With any in-cluster deployment, customization requirements will arise. + +Some common requirements would be: + +* `Service.spec.type`, to control whether a service is a `ClusterIP` or `LoadBalancer`. +* IP in the Service to assign to it. +* Arbitrary labels and annotations on generated resources. +* Any other arbitrary fields; the list is unbounded. Some examples would be: + * CPU and memory requests + * Service `externalTrafficPolicy` + * Affinity rules + +This GEP currently only aims to solve a subset of these concerns. Additional concerns may be addressed in future revisions or other GEPs. + +#### Gateway Type + +This is handled by [GEP-1651](https://github.com/kubernetes-sigs/gateway-api/pull/1653), so won't be described here. + +#### Gateway IP + +This section just clarifies an existing part of the spec, how to handle `.spec.addresses` for in-cluster implementations. +Like all other Gateway types, this should impact the address the `Gateway` is reachable at. + +For implementations using a `Service`, this means the `clusterIP` or `loadBalancerIP` (depending on the `Service` type). + +For example: + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: my-gateway +spec: + addresses: + - type: IPAddress + value: 1.1.1.1 + gatewayClassName: example + listeners: + - name: default + port: 80 + protocol: HTTP +``` + +This would generate a `Service` with `clusterIP` or `loadBalancerIP`, depending on the Service type. + +#### Labels and Annotations + +Labels and annotations for generated resources are specified in `infrastructure`: + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: my-gateway +spec: + infrastructure: + labels: + foo: bar + annotations: + name: my-annotation +``` + +These are both `map[string]string` types, just like in `ObjectMeta`. + +Any labels or annotations here are added to all generated resources. +Note this may mean an annotation intended for a `Service` may end up on a `Deployment` (for example). +This is typically not a concern; however, if an implementation is aware of specific meanings of certain labels or annotations, they MAY +exclude these from irrelevant resources. + +This is intended to clearly identify resources associated with a specific application, environment, or Gateway. +Additionally, it can be used support integration with the kitchen-sink of Kubernetes extensions which rely on labels and annotations. + +Validation will be added to prevent any usage with `gateway.networking.k8s.io/` prefix, to avoid conflicts with `gateway.networking.k8s.io/gateway-name` or other future additions. + +#### Arbitrary Customization + +GEP-1867 introduces a new `infrastructure` field, which allows customization of some common configurations (version, size, etc) +and allows a per-Gateway generic `parametersRef`. +This can be utilized for the remainder of customizations. + +### Resource Attachment + +Resources generated in response to the `Gateway` will have two attributes: + +* A `gateway.networking.k8s.io/gateway-name: ` label. +* A name `-`. This format is not strictly required for implementations, but strongly recommended for consistency in attachment. + +The generated resources MUST be in the same namespaces as the `Gateway`. + +Implementations MAY set `ownerReferences` to the `Gateway` in most cases, as well, but this is not required +as some implementations may have different cleanup mechanisms. + +The `gateway.networking.k8s.io/gateway-name` label and standardize resource naming format can be relied on to attach resources to. +While "Policy attachment" in Gateway API would use attachment to the actual `Gateway` resource itself, +many existing resources attach only to resources like `Deployment` or `Service`. + +An example using these: +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: gateway +spec: + gatewayClassName: example + listeners: + - name: default + hostname: "example.com" + port: 80 + protocol: HTTP +--- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: gateway +spec: + # Match the generated Deployment by reference + # Note: Do not use `kind: Gateway`. + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: gateway-example + minReplicas: 2 + maxReplicas: 5 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 50 +--- +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: gateway +spec: + minAvailable: 1 + selector: + # Match the generated Deployment by label + matchLabels: + gateway.networking.k8s.io/gateway-name: gateway +``` + +Note: there is [discussion](https://github.com/kubernetes-sigs/gateway-api/discussions/1355) around a way to attach a HPA to a Gateway directly. + +## API + +This GEP extends the `infrastructure` API introduced in [GEP-1867](../gep-1867/index.md). + +```go +type GatewayInfrastructure struct { + // Labels that should be applied to any resources created in response to this Gateway. + // + // For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. + // For other implementations, this refers to any relevant (implementation specific) "labels" concepts. + // + // An implementation may chose to add additional implementation-specific labels as they see fit. + // + // Support: Extended + // +kubebuilder:validation:MaxItems=8 + Labels map[string]string `json:"labels,omitempty"` + // Annotations that should be applied to any resources created in response to this Gateway. + // + // For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. + // For other implementations, this refers to any relevant (implementation specific) "annotations" concepts. + // + // An implementation may chose to add additional implementation-specific annotations as they see fit. + // + // Support: Extended + // +kubebuilder:validation:MaxItems=8 + Annotations map[string]string `json:"annotations,omitempty"` + ... +} +``` + +## Future Work + +* Allow various policies, [such as HPA](https://github.com/kubernetes-sigs/gateway-api/discussions/1355), to attach directly to `Gateway` rather than just `Deployment`. diff --git a/site-src/ko/geps/gep-1762/metadata.yaml b/site-src/ko/geps/gep-1762/metadata.yaml new file mode 100644 index 0000000000..2f5677ef7d --- /dev/null +++ b/site-src/ko/geps/gep-1762/metadata.yaml @@ -0,0 +1,12 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1762 +name: In Cluster Gateway Deployments +status: Standard +authors: + - howardjohn + - frankbu +relationships: + extendedBy: + - number: 1867 + name: Per-Gateway Infrastructure diff --git a/site-src/ko/geps/gep-1767/index.md b/site-src/ko/geps/gep-1767/index.md new file mode 100644 index 0000000000..3f1018bdb1 --- /dev/null +++ b/site-src/ko/geps/gep-1767/index.md @@ -0,0 +1,1009 @@ +# GEP 1767: CORS Filter + +* Issue: [#1767](https://github.com/kubernetes-sigs/gateway-api/issues/1767) +* Status: Experimental + +## TLDR +Cross-origin resource sharing (CORS) is an HTTP-header based mechanism that allows a web page to access restricted resources from a server on an origin (domain, scheme, or port) different than the domain that served the web page. +It's helpful to have a `HTTPCorsFilter` field in `HTTPRouteFilter` to handle the cross-origin requests before the response is sent to the client. + +## Goals + +* Support CORS filter in a `HTTPRoute` + +## Introduction +The CORS protocol is the current specification to support secure cross-origin requests and data transfers between clients and servers. + +A CORS request is an HTTP request that includes an `Origin` header. +An origin consists of three parts: the scheme, host and port. Two URLs have the same origin if they have the same scheme, host, and port. +All of the following URLs have the same origin. +```text + http://example.com/ + http://example.com:80/ + http://example.com/path/file +``` + +Each of the following URLs has a different origin from the others. +```text + http://example.com/ + http://example.com:8080/ + http://www.example.com/ + https://example.com:80/ + https://example.com/ + http://example.org/ + http://ietf.org/ +``` + +Before the actual cross-origin requests, clients will initiate an extra "preflight" request to determine whether the server will permit the actual requests. +The CORS "preflight" request uses `OPTIONS` as method and includes the following headers: + `Origin` request header indicates where a request originates from. + `Access-Control-Request-Method` request header lets the server know which HTTP method will be used when the actual cross-origin request is made. + `Access-Control-Request-Headers` is an optional request header indicates which headers the actual cross-origin request might use. + +The server response for the CORS "preflight" request includes the following headers: + `Access-Control-Allow-Origin` response header indicates whether the response can be shared with requested resource from the given `Origin`. + `Access-Control-Allow-Methods` response header specifies one or more HTTP methods are accepted by the server when accessing the requested resource. + `Access-Control-Allow-Headers` response header indicates which HTTP headers can be used during the actual cross-origin request. + +The `Access-Control-Max-Age` optional response header indicates how long (in seconds) the information provided by the headers `Access-Control-Allow-Methods` and `Access-Control-Allow-Headers` can be cached by client. The default value for `Access-Control-Max-Age` is 5 seconds. Until the time specified by `Access-Control-Max-Age` elapses, the client doesn't have to send another "preflight" request. + +The optional response header `Access-Control-Expose-Headers` controls which HTTP response headers are exposed to clients for the actual cross-origin request. + +If the server specifies the response header `Access-Control-Allow-Credentials: true`, the actual cross-origin request will be able to use credentials for getting sensitive resources. +Credentials are cookies, TLS client certificates, or authentication headers containing a username and password. + +After the server has permitted the CORS "preflight" request, the client will be able to send actual cross-origin request. +If the server doesn't want to allow cross-origin access, it will omit the CORS headers to the client. +Therefore, the client doesn't attempt the actual cross-origin request. + +In a simple cross-origin interaction, the client sends the request and cross-origin headers at the same time. These are usually GET data requests and are considered low-risk. + +For example, a client sends a GET request with cross-origin header `Origin`. +``` +GET /resource/foo HTTP/1.1 +Host: http.route.cors.com +Origin: https://foo.example +``` + +The server sets response header Access-Control-Allow-Origin with "*", which means that the requested resource can be accessed from the any `Origin`. +``` +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Access-Control-Allow-Methods: GET, HEAD, POST +Access-Control-Allow-Headers: Accept,Accept-Language,Content-Language,Content-Type,Range +``` + +Some HTTP requests are considered complex and require server confirmation before the actual cross-origin request is sent. Before the actual cross-origin requests, clients will initiate an extra "preflight" request to determine whether that the server will permit the actual requests. + +For example, a client sends a cross-origin "preflight" request for asking a server whether it would allow a PUT request before the actual cross-origin request is sent. +``` +OPTIONS /resource/foo HTTP/1.1 +Host: http.route.cors.com +Origin: https://foo.example +Access-Control-Request-Method: PUT +``` + +If the "preflight" request is denied, the requested resource will end up not being shared. +The server returns 200 OK but doesn't set the cross-origin response headers. +Therefore, the client doesn't attempt the actual cross-origin request. +``` +HTTP/1.1 200 OK +Content-Type: text/plain charset=UTF-8 +Content-Length: 0 +``` + +If the server allows it, it will respond with an OK status (i.e., 204 or 200) and the following response headers. +``` +HTTP/1.1 204 No Content +Access-Control-Allow-Origin: https://foo.example +Access-Control-Allow-Credentials: true +Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS +Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization +Access-Control-Expose-Headers: Content-Security-Policy +Access-Control-Max-Age: 1728000 +Content-Type: text/plain charset=UTF-8 +Content-Length: 0 +``` + +Then, the client will be able to send actual cross-origin request. +``` +PUT /resource/foo HTTP/1.1 +Host: http.route.cors.com +Keep-Alive: timeout=5, max=1000 +Origin: https://foo.example +Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l +``` + +At last, the cross-origin response headers will be added by the server to the response. +``` +Access-Control-Allow-Origin: https://foo.example +Access-Control-Allow-Credentials: true +Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS +Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization +Access-Control-Expose-Headers: Content-Security-Policy +``` + +## API +This GEP proposes to add a new field `HTTPCORSFilter` to `HTTPRouteFilter`. +If `HTTPCORSFilter` is set, then the gateway will generate the response of the "preflight" requests and send back it to the client directly. +For the actual cross-origin request, the gateway will add CORS headers to the response before it is sent to the client. + +```golang +// AllowCredentialsType describes valid value of config `AllowCredentials`. +// +// +kubebuilder:validation:Enum=true +type AllowCredentialsType string + +const ( + // The actual cross-origin request allows to include credentials. + AllowCredentials AllowCredentialsType = "true" +) + +const ( + // HTTPRouteFilterCORS can be used to add CORS headers to an + // HTTP response before it is sent to the client. + // + // Support in HTTPRouteRule: Extended + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterCORS HTTPRouteFilterType = "CORS" +) + +type HTTPRouteFilter struct { + // CORS defines a schema for a filter that responds to the + // cross-origin request based on HTTP response header. + // + // Support: Extended + // + // +optional + CORS *HTTPCORSFilter `json:"cors,omitempty"` +} + +// HTTPCORSFilter defines a filter that responds to the +// cross-origin request based on HTTP header. +type HTTPCORSFilter struct { + // AllowOrigins indicates whether the response can be shared with + // requested resource from the given `Origin`. + // + // The `Origin` consists of a scheme and a host, with an optional + // port, and takes the form `://(:)`. + // + // Valid values for scheme are: `http` and `https`. + // + // Valid values for port are any integer between 1 and 65535 + // (the list of available TCP/UDP ports). Note that, if not included, + // port `80` is assumed for `http` scheme origins, and port `443` + // is assumed for `https` origins. This may affect origin matching. + // + // The host part of the origin may contain the wildcard character `*`. + // These wildcard characters behave as follows: + // + // * `*` is a greedy match to the _left_, including any number of + // DNS labels to the left of its position. This also means that + // `*` will include any number of period `.` characters to the + // left of its position. + // * A wildcard by itself matches all hosts. + // + // An origin value that includes _only_ the `*` character + // indicates requests from all `Origin`s are allowed. + // + // When the `AllowOrigins` field is configured with multiple + // origins, it means the server supports clients from multiple + // origins. If the request `Origin` matches the configured + // allowed origins, the gateway must return the given `Origin` + // and sets value of the header `Access-Control-Allow-Origin` + // same as the `Origin` header provided by the client. + // + // The status code of a successful response to a "preflight" + // request is always an OK status (i.e., 204 or 200). + // + // Input: + // Origin: https://foo.example + // + // Config: + // allowOrigins: ["https://foo.example", "http://foo.example", "https://test.example", "http://test.example"] + // + // Output: + // Access-Control-Allow-Origin: https://foo.example + // + // If the request `Origin` does not match the configured allowed origins, + // the gateway returns 204/200 response but doesn't set the relevant + // cross-origin response headers. Alternatively, the gateway responds with + // 403 status to the "preflight" request is denied, coupled with omitting + // the CORS headers. The cross-origin request fails on the client side. + // Therefore, the client doesn't attempt the actual cross-origin request. + // + // Input: + // Origin: https://foo.example + // + // Config: + // allowOrigins: ["https://test.example", "http://test.example"] + // + // Output: + // + // The `Access-Control-Allow-Origin` response header can only use `*` + // wildcard as value when the `AllowCredentials` field is unspecified. + // + // Input: + // Origin: https://foo.example + // + // Config: + // allowOrigins: ["*"] + // + // Output: + // Access-Control-Allow-Origin: * + // + // When the `AllowCredentials` field is specified and `AllowOrigins` + // field specified with the `*` wildcard, the gateway must return a + // single origin in the value of the `Access-Control-Allow-Origin` + // response header, instead of specifying the `*` wildcard. The value + // of the header `Access-Control-Allow-Origin` is same as the `Origin` + // header provided by the client. + // + // Input: + // Origin: https://foo.example + // + // Config: + // allowOrigins: ["*"] + // allowCredentials: true + // + // Output: + // Access-Control-Allow-Origin: https://foo.example + // Access-Control-Allow-Credentials: true + // + // Support: Extended + // +listType=set + // +kubebuilder:validation:MaxItems=64 + AllowOrigins []string `json:"allowOrigins,omitempty"` + + // AllowCredentials indicates whether the actual cross-origin request + // allows to include credentials. + // + // The only valid value for the `Access-Control-Allow-Credentials` + // response header is true (case-sensitive). + // + // Input: + // Origin: https://foo.example + // + // Config: + // allowCredentials: true + // + // Output: + // Access-Control-Allow-Origin: https://foo.example + // Access-Control-Allow-Credentials: true + // + // If the credentials are not allowed in cross-origin requests, + // the gateway will omit the header `Access-Control-Allow-Credentials` + // entirely rather than setting its value to false. + // + // Support: Extended + // + // +optional + AllowCredentials AllowCredentialsType `json:"allowCredentials,omitempty"` + + // AllowMethods indicates which HTTP methods are supported + // for accessing the requested resource. + // + // Valid values are any method defined by RFC9110, along with the special + // value `*`, which represents all HTTP methods are allowed. + // + // Method names are case-sensitive, so these values are also case-sensitive. + // (See https://www.rfc-editor.org/rfc/rfc2616#section-5.1.1) + // + // Multiple method names in the value of the `Access-Control-Allow-Methods` + // response header are separated by a comma (","). + // + // A CORS-safelisted method is a method that is `GET`, `HEAD`, or `POST`. + // (See https://fetch.spec.whatwg.org/#cors-safelisted-method) + // The CORS-safelisted methods are always allowed, regardless of whether + // they are specified in the `AllowMethods` field. + // + // When the `AllowMethods` field is configured with one or more methods, + // the gateway must return the `Access-Control-Allow-Methods` response + // header which value is present in the `AllowMethods` field. + // + // If the HTTP method of the `Access-Control-Request-Method` request header + // is not included in the list of methods specified by the response header + // `Access-Control-Allow-Methods`, it will present an error on the client + // side. + // + // Input: + // Access-Control-Request-Method: PUT + // + // Config: + // allowMethods: ["GET", "POST", "DELETE", "PATCH", "OPTIONS"] + // + // Output: + // Access-Control-Allow-Methods: GET, POST, DELETE, PATCH, OPTIONS + // + // The `Access-Control-Allow-Methods` response header can only use `*` + // wildcard as value when the `AllowCredentials` field is unspecified. + // + // Input: + // Access-Control-Request-Method: PUT + // + // Config: + // allowMethods: ["*"] + // + // Output: + // Access-Control-Allow-Methods: * + // + // When the `AllowCredentials` field is specified and `AllowMethods` + // field specified with the `*` wildcard, the gateway must specify one + // HTTP method in the value of the Access-Control-Allow-Methods response + // header. The value of the header `Access-Control-Allow-Methods` is same + // as the `Access-Control-Request-Method` header provided by the client. + // If the header `Access-Control-Request-Method` is not included in the + // request, the gateway will omit the `Access-Control-Allow-Methods` + // response header, instead of specifying the `*` wildcard. A Gateway + // implementation may choose to add implementation-specific default + // methods. + // + // Input: + // Access-Control-Request-Method: PUT + // + // Config: + // allowMethods: ["*"] + // allowCredentials: true + // + // Output: + // Access-Control-Allow-Methods: PUT + // Access-Control-Allow-Credentials: true + // + // Support: Extended + // + // +listType=set + // +kubebuilder:validation:MaxItems=16 + AllowMethods []HTTPMethod `json:"allowMethods,omitempty"` + + // AllowHeaders indicates which HTTP request headers are supported + // for accessing the requested resource. + // + // Header names are not case-sensitive. + // + // Multiple header names in the value of the `Access-Control-Allow-Headers` + // response header are separated by a comma (","). + // + // When the `AllowHeaders` field is configured with one or more headers, + // the gateway must return the `Access-Control-Allow-Headers` response + // header which value is present in the `AllowHeaders` field. + // + // If any header name in the `Access-Control-Request-Headers` request header + // is not included in the list of header names specified by the response header + // `Access-Control-Allow-Headers`, it will present an error on the client side. + // + // If any header name in the `Access-Control-Allow-Headers` response header does + // not recognize by the client, it will also occur an error on the client side. + // + // Input: + // Access-Control-Request-Headers: Cache-Control, Content-Type + // + // Config: + // allowHeaders: ["DNT", "Keep-Alive", "User-Agent", "X-Requested-With", "If-Modified-Since", "Cache-Control", "Content-Type", "Range", "Authorization"] + // + // Output: + // Access-Control-Allow-Headers: DNT, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Range, Authorization + // + // A wildcard indicates that the requests with all HTTP headers are allowed. + // The `Access-Control-Allow-Headers` response header can only use `*` wildcard + // as value when the `AllowCredentials` field is unspecified. + // + // Input: + // Access-Control-Request-Headers: Content-Type, Cache-Control + // + // Config: + // allowHeaders: ["*"] + // + // Output: + // Access-Control-Allow-Headers: * + // + // When the `AllowCredentials` field is specified and `AllowHeaders` field + // specified with the `*` wildcard, the gateway must specify one or more + // HTTP headers in the value of the `Access-Control-Allow-Headers` response + // header. The value of the header `Access-Control-Allow-Headers` is same as + // the `Access-Control-Request-Headers` header provided by the client. If + // the header `Access-Control-Request-Headers` is not included in the request, + // the gateway will omit the `Access-Control-Allow-Headers` response header, + // instead of specifying the `*` wildcard. A Gateway implementation may choose + // to add implementation-specific default headers. + // + // Input: + // Access-Control-Request-Headers: Content-Type, Cache-Control + // + // Config: + // allowHeaders: ["*"] + // allowCredentials: true + // + // Output: + // Access-Control-Allow-Headers: Content-Type, Cache-Control + // Access-Control-Allow-Credentials: true + // + // Support: Extended + // + // +listType=set + // +kubebuilder:validation:MaxItems=64 + AllowHeaders []string `json:"allowHeaders,omitempty"` + + // ExposeHeaders indicates which HTTP response headers can be exposed + // to client-side scripts in response to a cross-origin request. + // + // A CORS-safelisted response header is an HTTP header in a CORS response + // that it is considered safe to expose to the client scripts. + // The CORS-safelisted response headers include the following headers: + // `Cache-Control` + // `Content-Language` + // `Content-Length` + // `Content-Type` + // `Expires` + // `Last-Modified` + // `Pragma` + // (See https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name) + // The CORS-safelisted response headers are exposed to client by default. + // + // When an HTTP header name is specified using the `ExposeHeaders` field, this + // additional header will be exposed as part of the response to the client. + // + // Header names are not case-sensitive. + // + // Multiple header names in the value of the `Access-Control-Expose-Headers` + // response header are separated by a comma (","). + // + // Config: + // exposeHeaders: ["Content-Security-Policy", "Content-Encoding"] + // + // Output: + // Access-Control-Expose-Headers: Content-Security-Policy, Content-Encoding + // + // A wildcard indicates that the responses with all HTTP headers are exposed + // to clients. The `Access-Control-Expose-Headers` response header can only use + // `*` wildcard as value when the `AllowCredentials` field is unspecified. + // + // Config: + // exposeHeaders: ["*"] + // + // Output: + // Access-Control-Expose-Headers: * + // + // Support: Extended + // + // +optional + // +listType=set + // +kubebuilder:validation:MaxItems=64 + ExposeHeaders []string `json:"exposeHeaders,omitempty"` + + // MaxAge indicates the duration (in seconds) for the client to cache + // the results of a "preflight" request. + // + // The information provided by the `Access-Control-Allow-Methods` and + // `Access-Control-Allow-Headers` response headers can be cached by the + // client until the time specified by `Access-Control-Max-Age` elapses. + // + // The default value of `Access-Control-Max-Age` response header is + // 5 (seconds). + // + // When the `MaxAge` field is unspecified, the gateway sets the response + // header "Access-Control-Max-Age: 5" by default. + // + // Config: + // maxAge: 1728000 + // + // Output: + // Access-Control-Max-Age: 1728000 + // + // Support: Extended + // + // +optional + // +kubebuilder:default=5 + // +kubebuilder:validation:Minimum=1 + MaxAge int32 `json:"maxAge,omitempty"` +} +``` + +## Examples + +The following example shows how a HTTPRoute supports secure cross-origin requests and data transfers between clients and servers. + +### Simple cross-origin interaction + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-route-cors +spec: + hostnames: + - http.route.cors.com + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: http-gateway + rules: + - backendRefs: + - kind: Service + name: http-route-cors + port: 80 + matches: + - path: + type: PathPrefix + value: /resource/foo + filters: + - cors: + - allowOrigins: + - * + allowMethods: + - GET + - HEAD + - POST + allowHeaders: + - Accept + - Accept-Language + - Content-Language + - Content-Type + - Range + type: CORS +``` + +A client sends a GET request with cross-origin header `Origin`. +``` +GET /resource/foo HTTP/1.1 +Host: http.route.cors.com +Origin: https://foo.example + +``` + +The cross-origin response headers will be added by the gateway to the response based on the above HTTPRoute. +The gateway returns an Access-Control-Allow-Origin header with "*", which means that the requested resource can be accessed from the any `Origin`. +``` +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Access-Control-Allow-Methods: GET, HEAD, POST +Access-Control-Allow-Headers: Accept,Accept-Language,Content-Language,Content-Type,Range +``` + +### Complex cross-origin interaction + +Some HTTP requests are considered complex and require server confirmation before the actual cross-origin request is sent. Before the actual cross-origin requests, clients will initiate an extra "preflight" request to determine whether that the server will permit the actual requests. + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-route-cors +spec: + hostnames: + - http.route.cors.com + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: http-gateway + rules: + - backendRefs: + - kind: Service + name: http-route-cors + port: 80 + matches: + - path: + type: PathPrefix + value: /resource/foo + filters: + - cors: + - allowOrigins: + - https://foo.example + - http://foo.example + allowCredentials: "true" + allowMethods: + - GET + - PUT + - POST + - DELETE + - PATCH + - OPTIONS + allowHeaders: + - DNT + - X-CustomHeader + - Keep-Alive + - User-Agent + - X-Requested-With + - If-Modified-Since + - Cache-Control + - Content-Type + - Authorization + exposeHeaders: + - Content-Security-Policy + maxAge: 1728000 + type: CORS +``` + +A client sends a cross-origin "preflight" request for asking a server whether it would allow a PUT request before the actual cross-origin request is sent. +``` +OPTIONS /resource/foo HTTP/1.1 +Host: http.route.cors.com +Origin: https://foo.example +Access-Control-Request-Method: PUT +``` + +The status code of a successful response to a "preflight" request is an OK status (i.e., 204 or 200). +Based on the above HTTPRoute, a successful "preflight" response will be generated by the gateway. +Moreover, the gateway will send the "preflight" response to the client directly. + +``` +HTTP/1.1 204 No Content +Access-Control-Allow-Origin: https://foo.example +Access-Control-Allow-Credentials: true +Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS +Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization +Access-Control-Expose-Headers: Content-Security-Policy +Access-Control-Max-Age: 1728000 +Content-Type: text/plain charset=UTF-8 +Content-Length: 0 +``` + +Then, the client will be able to send actual cross-origin request. +``` +PUT /resource/foo HTTP/1.1 +Host: http.route.cors.com +Keep-Alive: timeout=5, max=1000 +Origin: https://foo.example +Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l +``` + +At last, the cross-origin response headers will be added by the gateway to the response based on the HTTPRoute. +``` +Access-Control-Allow-Origin: https://foo.example +Access-Control-Allow-Credentials: true +Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS +Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization +Access-Control-Expose-Headers: Content-Security-Policy +``` + +## Prior Art +Some implementations already support CORS. + +### Ingress-NGINX supports CORS with the following annotations: + +* nginx.ingress.kubernetes.io/enable-cors enables CORS in an ingress rule. The default value is false. +* nginx.ingress.kubernetes.io/cors-allow-methods controls which HTTP methods are accepted by the server. +* nginx.ingress.kubernetes.io/cors-allow-headers controls which HTTP headers are accepted by the server. +* nginx.ingress.kubernetes.io/cors-expose-headers controls which headers are exposed to response. +* nginx.ingress.kubernetes.io/cors-allow-origin controls what's the allowed `Origin` for the requested resource. +* nginx.ingress.kubernetes.io/cors-allow-credentials controls whether the actual cross-origin request allows to include credentials. The default value is true. +* nginx.ingress.kubernetes.io/cors-max-age controls how long "preflight" requests can be cached by client. The default value is 1728000 seconds (i.e., 20 days). + +For example, the following rule restricts cross-origin requests to the requested resource originating from https://foo.example using HTTP GET/PUT/POST/DELETE/PATCH/OPTIONS and sets Access-Control-Allow-Credentials header to true by default. HTTP headers "Origin,No-Cache,X-Requested-With,If-Modified-Since,Pragma,Last-Modified,Cache-Control,Expires,Content-Type,X-E4M-With,userId,token,authorization,groot-jwt,x-mokelay-custom-header,EagleEye-UserData,EagleEye-TraceId,EagleEye-RpcId,x-xsrf-token,cn-gw-custom-headers,X-XSRF-TOKEN,DNT,X-CustomHeader,Keep-Alive,User-Agent" can be used during the actual cross-origin request. The default value of header Access-Control-Max-Age is 20 days. + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + nginx.ingress.kubernetes.io/enable-cors: "true" + nginx.ingress.kubernetes.io/cors-allow-origin: 'https://foo.example' + nginx.ingress.kubernetes.io/cors-allow-methods: GET, PUT, POST, DELETE, PATCH, OPTIONS + nginx.ingress.kubernetes.io/cors-allow-headers: Origin,No-Cache,X-Requested-With,If-Modified-Since,Pragma,Last-Modified,Cache-Control,Expires,Content-Type,X-E4M-With,userId,token,authorization,groot-jwt,x-mokelay-custom-header,EagleEye-UserData,EagleEye-TraceId,EagleEye-RpcId,x-xsrf-token,cn-gw-custom-headers,X-XSRF-TOKEN,DNT,X-CustomHeader,Keep-Alive,User-Agent + name: ingress-cors-test +spec: + ingressClassName: nginx-default + rules: + - host: foo.cors.com + http: + paths: + - path: / + pathType: Exact + backend: + service: + name: cors-test-service + port: + number: 80 +``` + +### NGINX Ingress Controller supports CORS with CRDs VirtualServer and VirtualServerRoute resources: + +* Action.Proxy.ResponseHeaders field of CRDs VirtualServer and VirtualServerRoute modifies the headers of the response to the client. + +```yaml +responseHeaders: + description: ProxyResponseHeaders defines the response + headers manipulation in an ActionProxy. + properties: + add: + items: + description: AddHeader defines an HTTP Header + with an optional Always field to use with + the add_header NGINX directive. + properties: + always: + type: boolean + name: + type: string + value: + type: string + type: object + type: array +``` + +* The name field is the name of the header. +* The value field is the value of the header. +* If the always field is true, the header will be added regardless of the response code. + +The following example shows how the VirtualServer and VirtualServerRoute resources supports enabling and configuring CORS. +The rule restricts cross-origin requests to the requested resource originating from https://foo.example using HTTP GET/POST/PATCH, and sets the Access-Control-Allow-Credentials header to true. +Moreover, HTTP headers "Origin,No-Cache,X-Requested-With,If-Modified-Since,Pragma" can be used during the actual cross-origin request. +At last, it sets an expiry period of 48 hours for the client to cache the results of a "preflight" request. + +```yaml +responseHeaders: + add: + - name: Access-Control-Allow-Origin + value: "https://foo.example" + - name: Access-Control-Allow-Credentials + value: "true" + - name: Access-Control-Allow-Methods + value: "GET, POST, PATCH" + - name: Access-Control-Allow-Headers + value: "Origin,No-Cache,X-Requested-With,If-Modified-Since,Pragma" + - name: Access-Control-Max-Age + value: "172800" +``` + +### Istio supports CORS with CRD VirtualService: + +* allowOrigins: string patterns that match allowed origins. +* allowMethods: a list of HTTP methods allowed to access the resource. +* allowHeaders: a list of HTTP headers that can be used when requesting the resource. +* exposeHeaders: a list of HTTP headers that the browsers are allowed to access. +* maxAge: how long the results of a preflight request can be cached. +* allowCredentials: whether the caller is allowed to send the actual request (not the preflight) using credentials. +* unmatchedPreflights: whether preflight requests not matching the configured allowed origin shouldn’t be forwarded to the upstream. + +```yaml +http: + description: An ordered list of route rules for HTTP traffic. + items: + properties: + corsPolicy: + description: Cross-Origin Resource Sharing policy (CORS). + properties: + allowCredentials: + description: Indicates whether the caller is allowed to send the actual request (not the preflight) using credentials. + nullable: true + type: boolean + allowHeaders: + description: List of HTTP headers that can be used when requesting the resource. + items: + type: string + type: array + allowMethods: + description: List of HTTP methods allowed to access the resource. + items: + type: string + type: array + allowOrigins: + description: String patterns that match allowed origins. + items: + oneOf: + - not: + anyOf: + - required: + - exact + - required: + - prefix + - required: + - regex + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + type: string + prefix: + type: string + regex: + description: '[RE2 style regex-based match](https://github.com/google/re2/wiki/Syntax).' + type: string + type: object + type: array + exposeHeaders: + description: A list of HTTP headers that the browsers are allowed to access. + items: + type: string + type: array + maxAge: + description: Specifies how long the results of a preflight request can be cached. + type: string + x-kubernetes-validations: + - message: must be a valid duration greater than 1ms + rule: duration(self) >= duration('1ms') + unmatchedPreflights: + description: |- + Indicates whether preflight requests not matching the configured allowed origin shouldn't be forwarded to the upstream. + + Valid Options: FORWARD, IGNORE + enum: + - UNSPECIFIED + - FORWARD + - IGNORE + type: string + type: object +``` + +In the following example, the rule restricts cross-origin requests to the requested resource originating from https://foo.example and http://foo.example using HTTP GET/HEAD/POST. It sets the Access-Control-Allow-Credentials header to false. The credentials will not be allowed in the actual cross-origin requests. +Moreover, only the HTTP header "X-Foo-Example" can be used during the actual cross-origin request. At last, it sets an expiry period of 1 day for the browser to cache the results of a "preflight" request. + +```yaml +apiVersion: networking.istio.io/v1 +kind: VirtualService +metadata: + name: http-route-cors +spec: + hosts: + - http.route.cors.com + http: + - route: + - destination: + host: cors.svc.cluster.local + subset: v1 + corsPolicy: + allowOrigins: + - exact: https://foo.example + - exact: http://foo.example + allowMethods: + - GET + - HEAD + - POST + allowCredentials: false + allowHeaders: + - X-Foo-Example + maxAge: "24h" +``` + +### Traefik supports CORS with CRD Middleware: + +* CORS Headers of HTTP Headers middleware manages the cross-origin response headers. + +```yaml +headers: +description: |- + Headers holds the headers middleware configuration. + This middleware manages the requests and responses headers. + More info: https://doc.traefik.io/traefik/v3.2/middlewares/http/headers/#customrequestheaders +properties: + accessControlAllowCredentials: + description: AccessControlAllowCredentials defines whether the + request can include user credentials. + type: boolean + accessControlAllowHeaders: + description: AccessControlAllowHeaders defines the Access-Control-Allow-Headers + values sent in preflight response. + items: + type: string + type: array + accessControlAllowMethods: + description: AccessControlAllowMethods defines the Access-Control-Allow-Methods + values sent in preflight response. + items: + type: string + type: array + accessControlAllowOriginList: + description: AccessControlAllowOriginList is a list of allowable + origins. Can also be a wildcard origin "*". + items: + type: string + type: array + accessControlAllowOriginListRegex: + description: AccessControlAllowOriginListRegex is a list of allowable + origins written following the Regular Expression syntax (https://golang.org/pkg/regexp/). + items: + type: string + type: array + accessControlExposeHeaders: + description: AccessControlExposeHeaders defines the Access-Control-Expose-Headers + values sent in preflight response. + items: + type: string + type: array + accessControlMaxAge: + description: AccessControlMaxAge defines the time that a preflight + request may be cached. + format: int64 + type: integer + addVaryHeader: + description: AddVaryHeader defines whether the Vary header is + automatically added/updated when the AccessControlAllowOriginList + is set. + type: boolean +``` + +* accessControlAllowCredentials: whether the request can include user credentials. +* accessControlAllowHeaders: a list of headers can be used during cross-origin requests. +* accessControlAllowMethods: a list of methods can be used during cross-origin requests. +* accessControlAllowOriginList: a list of allowable origins. +* accessControlAllowOriginListRegex: a list of allowable origins written following the Regular Expression syntax. +* accessControlExposeHeaders: which headers are safe to expose to the api of a CORS API specification. +* accessControlMaxAge: how many seconds a preflight request can be cached. +* addVaryHeader: whether the Vary header should be added or modified to demonstrate that server responses can differ based on the value of the origin header. + +In the example below, the rule restricts cross-origin requests to the requested resource originating from https://foo.example and http://foo.example using HTTP GET/OPTIONS/PUT. It specifies the response header Access-Control-Allow-Credentials to true, the actual cross-origin request will be able to use credentials for getting sensitive resources. Moreover, all HTTP headers can be used during the actual cross-origin request. At last, it sets an expiry period of 100 seconds for the browser to cache the results of a "preflight" request. + +```yaml +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: cors-header +spec: + headers: + accessControlAllowMethods: + - "GET" + - "OPTIONS" + - "PUT" + accessControlAllowHeaders: + - "*" + accessControlAllowOriginList: + - "https://foo.example" + - "http://foo.example" + accessControlAllowCredentials: true + accessControlMaxAge: 100 + addVaryHeader: true +``` + +## Alternatives Considered +### Use top level field in HTTPRouteRule to implement CORS +As suggested in [this comment](https://github.com/kubernetes-sigs/gateway-api/pull/3435/#discussion_r1874186947), a new field `CORS` is added to `HTTPRouteRule`, which allows for handling the cross-origin requests before the response is sent to the client. This is similar to the `Timeouts` field in `HTTPRouteRule`. + +```golang +type HTTPRouteRule struct { + Name *SectionName `json:"name,omitempty"` + + Matches []HTTPRouteMatch `json:"matches,omitempty"` + + Filters []HTTPRouteFilter `json:"filters,omitempty"` + + BackendRefs []HTTPBackendRef `json:"backendRefs,omitempty"` + + Timeouts *HTTPRouteTimeouts `json:"timeouts,omitempty"` + + Retry *HTTPRouteRetry `json:"retry,omitempty"` + + SessionPersistence *SessionPersistence `json:"sessionPersistence,omitempty"` + + // CORS defines the CORS rules that respond to the + // cross-origin request based on HTTP response header. + // + // Support: Extended + // + // +optional + CORS *HTTPCORS `json:"cors,omitempty"` +} +``` + +If a filter logically as a +```rust +fn run_filter(req: HTTPRequest) -> FilterResponse; +enum FilterResponse { + Request(HTTPRequest), + Response(HTTPResponse) +``` + +A `Timeouts` doesn't really meet that, but `CORS` does: +```rust +fn run_filter(req: HTTPRequest) -> FilterResponse { + if req.method == origin { return Response(cors_response()) } + return Request(req) +} +``` + +Moreover, CORS is a HTTP feature based on HTTP-header. This fits as a filter. + +## References +* [RFC2616](https://www.rfc-editor.org/rfc/rfc2616) +* [RFC6454](https://www.rfc-editor.org/rfc/rfc6454) +* [RFC7230](https://www.rfc-editor.org/rfc/rfc7230) +* [RFC9110](https://www.rfc-editor.org/rfc/rfc9110) +* [RFC9111](https://www.rfc-editor.org/rfc/rfc9111) +* [Fetch Living Standard](https://fetch.spec.whatwg.org) +* [Ingress-NGINX `Enable CORS`](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#enable-cors) +* [NGINX Ingress Controller `ResponseHeaders`](https://docs.nginx.com/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#actionproxyresponseheaders) +* [Istio `CorsPolicy`](https://istio.io/latest/docs/reference/config/networking/virtual-service/#CorsPolicy) +* [Traefik `CORS Headers`](https://doc.traefik.io/traefik/middlewares/http/headers/#cors-headers) diff --git a/site-src/ko/geps/gep-1767/metadata.yaml b/site-src/ko/geps/gep-1767/metadata.yaml new file mode 100644 index 0000000000..c7fe532b81 --- /dev/null +++ b/site-src/ko/geps/gep-1767/metadata.yaml @@ -0,0 +1,15 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1767 +name: CORS Filter +status: Experimental +authors: + - lianglli + - robscott + - EyalPazz +references: + - https://github.com/kubernetes-sigs/gateway-api/pull/3435 + - https://github.com/kubernetes-sigs/gateway-api/pull/3637 + - https://github.com/kubernetes-sigs/gateway-api/pull/3656 + - https://github.com/kubernetes-sigs/gateway-api/pull/3668 + diff --git a/site-src/ko/geps/gep-1867/index.md b/site-src/ko/geps/gep-1867/index.md new file mode 100644 index 0000000000..cf66436290 --- /dev/null +++ b/site-src/ko/geps/gep-1867/index.md @@ -0,0 +1,160 @@ +# GEP-1867: Per-Gateway Infrastructure + +* Status: Standard +* Issue: [#1867](https://github.com/kubernetes-sigs/gateway-api/issues/1867) + +## Overview + +`Gateway`s represent a piece of infrastructure implemented by cloud load balancers, in-cluster deployments, or other mechanisms. +These often need vendor-specific configuration outside the scope of existing APIs (e.g. "size" or "version" of the infrastructure to provision). + +Today `GatewayClass.spec.parametersRef` is available to attach arbitrary configuration to a `GatewayClass`. + +This GEP will explain why that is not sufficient to meet common use cases, and introduce a new field - `infrastructure` - to address these cases. + +Related discussions: +* [Support cluster-local Gateways](https://github.com/kubernetes-sigs/gateway-api/discussions/1247) +* [Scaling Gateway Resources](https://github.com/kubernetes-sigs/gateway-api/discussions/1355) +* [Manual deployments](https://github.com/kubernetes-sigs/gateway-api/issues/1687) +* [Merging Gateways](https://github.com/kubernetes-sigs/gateway-api/pull/1863) +* [In Cluster Gateway Deployments](https://github.com/kubernetes-sigs/gateway-api/pull/1757) + +## Goals + +* Provide the ability to configure arbitrary (implementation specific) attributes about a **specific Gateway**. +* Provide the ability to configure a standardized set of attributes about a **specific Gateway**. + +## Why not GatewayClass parameters? + +`GatewayClass.spec.parametersRef` is the existing mechanism to configure arbitrary fields on a Gateway. +However, this introduces operational challenges when configuring Gateways. + +### Scope + +As a `Gateway` manager (with RBAC permissions to a specific `Gateway`) I should be able to declaratively make changes to that `Gateway` without the need for access to cluster-scoped resources (`GatewayClass`) and without affecting other `Gateways` managed by the same `GatewayClass`. +This has been previously discussed in [this issue](https://github.com/kubernetes-sigs/gateway-api/issues/567). + +As a cluster scoped resource, `GatewayClass` does not meet this requirement. +This restricts customization use cases to either a few pre-provisioned classes by the admin, or running in an environment where the "Infrastructure Provider" and "Cluster Operator" are the same roles. +The distinction between these roles is explicitly called out on the [homepage](../../index.md#what-is-the-gateway-api). + +### Custom Resource + +`parametersRef` is entirely a generic implementation-specific meaning. +This means implementations will either need a custom CRD or use untyped resources like ConfigMap. +Neither of these have any consistency between implementations. +While there will always be some vendor-specific requirements, there are also a number of configuration aspects of a Gateway that are common between implementations. +However, these cannot currently be expressed in a vendor-neutral way. + +The original motivation behind `parametersRef` was for implementation specific concepts, while portable comments could be added into the API as first-class fields, but this has not been done (yet). + +Additionally, there is hesitancy to use a CRD (which leads to CRD proliferation), which pushes users towards untyped ConfigMaps which are not much better than annotations. +The scoping, as mentioned above, is also a bit awkward of a cluster scoped resource pointing to a namespaced object. + +### Separation of concerns + +While there is value out of providing class-wide options as defaults, there is also value in providing these options on the object (Gateway) directly. + +Some parallels in existing APIs: + +[Policy Attachment](../../reference/policy-attachment.md) offers a hierarchy of defaults and overrides, allowing attachment to GatewayClass and Gateway. +This is similar to our needs here, but representing infrastructure configuration as a "Policy" is a bit problematic, and the existing mechanisms have no hierarchy. + +In core Kubernetes, Pods declare their requirements (for example, CPU requests) inline in the Pod resource; there is not a `ResourceClass` API that abstracts these further. +These higher level abstractions are handled by layered APIs (whether this is a CRD, an admission webhook, CI/CD tooling, etc). +This allows users the flexibility to easily configure things per-pod basis. +If the infrastructure admin wants to impose defaults or requirements on this flexibility, they are able to do so (in fact, `LimitRanger` provides a built in mechanism to do so). + +### Dynamic Changes + +Currently, the spec recommends `GatewayClass` to be used as a *template*. +Changes to it are not expected to change deployed `Gateway`s. + +This makes usage problematic in a declarative way. +For example, if I wanted to represent a `version` field and change that to trigger an upgrade, I would need to create an entirely new `Gateway`. + +## API + +In order to address the concerns above, I propose a standard `infrastructure` API is added to `Gateway`. + +The exact fields are out of scope for this GEP and will be handled by additional GEPs. +One example GEP already depending on this is [GEP-1651](../gep-1651/index.md). + +The fields as defined below are, at time of writing, the existing fields covered by this GEP. More fields may be added as needed. + +```go +type GatewaySpec struct { + // Infrastructure defines infrastructure level attributes about this Gateway instance. + // + // Support: Extended + // + // +optional + Infrastructure GatewayInfrastructure `json:"infrastructure"` + // ... +} + +type GatewayInfrastructure struct { + // Labels that SHOULD be applied to any resources created in response to this Gateway. + // + // For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. + // For other implementations, this refers to any relevant (implementation specific) "labels" concepts. + // + // An implementation may chose to add additional implementation-specific labels as they see fit. + // + // Support: Extended + // + // +optional + // +kubebuilder:validation:MaxProperties=8 + Labels map[AnnotationKey]AnnotationValue `json:"labels,omitempty"` + + // Annotations that SHOULD be applied to any resources created in response to this Gateway. + // + // For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. + // For other implementations, this refers to any relevant (implementation specific) "annotations" concepts. + // + // An implementation may chose to add additional implementation-specific annotations as they see fit. + // + // Support: Extended + // + // +optional + // +kubebuilder:validation:MaxProperties=8 + Annotations map[AnnotationKey]AnnotationValue `json:"annotations,omitempty"` + + // ParametersRef is a reference to a resource that contains the configuration + // parameters corresponding to the Gateway. This is optional if the + // controller does not require any additional configuration. + // + // This follows the same semantics as GatewayClass's `parametersRef`, but on a per-Gateway basis + // + // The Gateway's GatewayClass may provide its own `parametersRef`. When both are specified, + // the merging behavior is implementation specific. + // It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway. + // + // Support: Implementation-specific + // + // +optional + ParametersRef *LocalParametersReference `json:"parametersRef,omitempty"` +} + +type GatewayClassInfrastructure struct { +} +``` + +!!! warning + Modifying pod labels via `infrastructure.labels` could result in data plane pods being replaced (depending on the implementation). The way in which the pods are replaced is implementation specific and may result in downtime. Implementations should document how they handle changes to `infrastructure.labels`. + +### API Principles + +For any given field, we will need to make two decisions: +* whether this should be a first-class field or a generic `parametersRef`. +* whether this field should be configurable on a Gateway and/or GatewayClass level + +The choice to use an extension (`parametersRef`) or first-class field is a well known problem across the API, and the same logic will be used here. +Fields that are generally portable across implementations and have wide-spread demand and use cases will be promoted to first-class fields, +while vendor specific or niche fields will remain extensions. +Because infrastructure is somewhat inherently implementation specific, it is likely most fields will be Extended or ImplementationSpecific. +However, there are still a variety of concepts that have some meaning between implementations that can provide value to users. + +### Status + +At this time, no fields defined as part of this GEP are exposed via `status`. diff --git a/site-src/ko/geps/gep-1867/metadata.yaml b/site-src/ko/geps/gep-1867/metadata.yaml new file mode 100644 index 0000000000..fb150e544a --- /dev/null +++ b/site-src/ko/geps/gep-1867/metadata.yaml @@ -0,0 +1,11 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1867 +name: Per-Gateway Infrastructure +status: Standard +authors: + - howardjohn +relationships: + extends: + - number: 1762 + name: In Cluster Gateway Deployments diff --git a/site-src/ko/geps/gep-1897/1897-TLStermtypes.png b/site-src/ko/geps/gep-1897/1897-TLStermtypes.png new file mode 100644 index 0000000000..53e258ff78 Binary files /dev/null and b/site-src/ko/geps/gep-1897/1897-TLStermtypes.png differ diff --git a/site-src/ko/geps/gep-1897/index.md b/site-src/ko/geps/gep-1897/index.md new file mode 100644 index 0000000000..9f2a9918f9 --- /dev/null +++ b/site-src/ko/geps/gep-1897/index.md @@ -0,0 +1,414 @@ +# GEP-1897: BackendTLSPolicy - Explicit Backend TLS Connection Configuration + +* Issue: [#1897](https://github.com/kubernetes-sigs/gateway-api/issues/1897) +* Status: Experimental + +## TLDR + +This document specifically addresses the topic of conveying HTTPS from the Gateway +dataplane to the backend (backend TLS termination), and intends to satisfy the single +use case “As a client implementation of Gateway API, I need to know how to connect to +a backend pod that has its own certificate”. TLS configuration can be a nebulous topic, +so in order to drive resolution this GEP focuses only on this single piece of functionality. + +Furthermore, for Gateway API to handle the case where the service or backend owner is doing their own TLS, _and_ +the service or backend owner wants to validate the clients connecting to it, two things need to happen: + +- The service or backend owner has to provide a method for the Gateway owner to retrieve a certificate. +- Gateway API has to provide a way for the Gateway to configure and apply the validation options. + +## Immediate Goals + +1. The solution must satisfy the following use case: the backend pod has its own +certificate and the gateway implementation client needs to know how to connect to the +backend pod. (Use case #4 in [Gateway API TLS Use Cases](#references)) +2. In terms of the Gateway API personas, only the application developer persona applies in this +solution. The application developer should control the gateway to backend TLS settings, +not the cluster operator, as requiring a cluster operator to manage certificate renewals +and revocations would be extremely cumbersome. +3. The solution should consider client certificate settings used in the TLS handshake **from +Gateway to backend**, such as server name indication, trusted certificates, +and CA certificates. + +## Longer Term Goals + +These are worthy goals, but deserve a different GEP for proper attention. This GEP is concerned entirely with the +controlplane, i.e. the hop between gateway and backend. + +1. [TCPRoute](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.TCPRoute) and +[GRPCRoute](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.GRPCRoute) use cases +are not addressed here, because at this point in time these two route types are not graduated to beta. +2. Mutual TLS (mTLS) use cases are intentionally out of scope for this GEP for two reasons. First, the design of Gateway +API is backend-attached and does not currently support mutual authentication, and also because this GEP does not +address the case where connections to TLS are **implicitly configured** on behalf of the user, which is the norm for mTLS. +This GEP is about the case where an application developer needs to **explicitly express** that they expect TLS when +there is no automatic, implicit configuration available. +3. Service mesh use cases are not addressed here because this GEP is specifically concerned with the connection between +Gateways and Backends, not Service to Service. Service mesh use cases should ignore the design components described in +this proposal. + +## Non-Goals + +These are worthy goals, but will not be covered by this GEP. + +1. Changes to the existing mechanisms for edge or passthrough TLS termination +2. Providing a mechanism to decorate multiple route instances +3. TLSRoute use cases +4. UDPRoute use cases +5. Controlling TLS versions or cipher suites used in TLS handshakes. (Use case #5 in [Gateway API TLS Use Cases](#references)) +6. Controlling certificates used by more than one workload (#6 in [Gateway API TLS Use Cases](#references)) +7. Client certificate settings used in TLS **from external clients to the +Listener** (#7 in [Gateway API TLS Use Cases](#references)) +8. Providing a mechanism for the cluster operator to override gateway to backend TLS settings. + +## Already Solved TLS Use Cases + +These are worthy goals that are already solved and thus will not be modified by the implementation. + +1. Termination of TLS for HTTP routing (#1 in [Gateway API TLS Use Cases](#references)) +2. HTTPS passthrough use cases (#2 in [Gateway API TLS Use Cases](#references)) +3. Termination of TLS for non-HTTP TCP streams (#3 in [Gateway API TLS Use Cases](#references)) + +## Overview - what do we want to do? + +Given that the current ingress solution specifies **edge** TLS termination (from the client to +the gateway), and how to handle **passthrough** TLS (from the client to the backend pod), this +proposed ingress solution specifies TLS origination to the **backend** (from the gateway to the +backend pod). As mentioned, this solution satisfies the use case in which the backend pod +has its own certificate and the gateway client needs to know how to connect to the backend pod. + +![image depicting TLS termination types](images/1897-TLStermtypes.png "TLS termination types") + +Gateway API is missing a mechanism for separately providing the details for the backend TLS handshake, +including (but not limited to): + +* intent to use TLS on the backend hop +* client certificate of the gateway +* system certificates to use in the absence of client certificates + +## Purpose - why do we want to do this? + +This proposal is _very_ tightly scoped because we have tried and failed to address this well-known +gap in the API specification. The lack of support for this fundamental concept is holding back +Gateway API adoption by users that require a solution to the use case. One of the recurring themes +that has held up the prior art has been interest related to service mesh, and as such this proposal +focuses explicitly on the ingress use case in the initial round. Another reason for the tight scope +is that we have been too focused on a generic representation of everything that TLS can do, which +covers too much ground to address in a single GEP. + +## The history of backend TLS + +Work on this topic has spanned over three years, as documented in our repositories and other references, +and summarized below. + +In January 2020, in issue [TLS Termination Policy #52](https://github.com/kubernetes-sigs/gateway-api/issues/52), +this use case was discussed. The discussion ended after being diverted by +[KEP: Adding AppProtocol to Services and Endpoints #1422](https://github.com/kubernetes/enhancements/pull/1422), +which was implemented and later reverted. + +In February 2020, [HTTPRoute: Add Reencrypt #81](https://github.com/kubernetes-sigs/gateway-api/pull/81) +added the dataplane feature as “reencrypt”, but it went stale and was closed in favor of the work done in the +next paragraph, which unfortunately didn’t implement the backend TLS termination feature. + +In August 2020, it resurfaced with a [comment](https://github.com/kubernetes-sigs/gateway-api/pull/256/files#r472734392) +on this pull request: [tls: introduce mode and sni to cert matching behavior](https://github.com/kubernetes-sigs/gateway-api/pull/256/files#top). +The backend TLS termination feature was deferred at that time. Other TLS discussion was documented in +[[SIG-NETWORK] TLS config in service-apis](https://docs.google.com/document/d/15fkzMrhN_7tA-i2mHKwZpqcjN1o2Pe9Am9Qt828x1lo/edit#heading=h.wym7wehwll44) +, a list of TLS features that had been collected in June 2020, itself based on spreadsheet +[Service API: TLS related issues](https://docs.google.com/spreadsheets/d/18KE61Y6InCmoQHZcbrYYRZS5Cnt7n33s5dTxUlhHgIA/edit#gid=0). + +In December 2021, this was discussed as a beta blocker in issue +[Docs mentions Reencrypt for HTTPRoute and TLSRoute is available #968](https://github.com/kubernetes-sigs/gateway-api/issues/968). + +A March 2022 issue documents another request for it: [Provide a way to configure TLS from a Gateway to Backends #1067](https://github.com/kubernetes-sigs/gateway-api/issues/1067) + +A June 2022 issue documents a documentation issue related to it: +[Unclear how to specify upstream (webserver) HTTP protocol #1244](https://github.com/kubernetes-sigs/gateway-api/discussions/1244) + +A July 2022 discussion [Specify Re-encrypt TLS Termination (i.e., Upstream TLS) #1285](https://github.com/kubernetes-sigs/gateway-api/discussions/1285) +collected most of the historical context preceding the backend TLS termination feature, with the intention of +collecting evidence that this feature is still unresolved. This was followed by +[GEP: Describe Backend Properties #1282](https://github.com/kubernetes-sigs/gateway-api/issues/1282). + +In August 2022, [Add Provisional GEP-1282 document #1333](https://github.com/kubernetes-sigs/gateway-api/pull/1333) +was created, and in October 2022, a GEP update with proposed implementation +[GEP-1282 Backend Properties - Update implementation #1430](https://github.com/kubernetes-sigs/gateway-api/pull/1430) +was followed by intense discussion and closed in favor of a downsize in scope. + +In January 2023 we closed GEP-1282 and began a new discussion on enumerating TLS use cases in +[Gateway API TLS Use Cases](#references), for the purposes of a clear definition and separation of concerns. +This GEP is the outcome of the TLS use case #4 in +[Gateway API TLS Use Cases](#references) as mentioned in the Immediate Goals section above. + +## API + +To allow the gateway client to know how to connect to the backend pod, when the backend pod has its own +certificate, we implement a metaresource named `BackendTLSPolicy`, that was previously introduced with the name +`TLSConnectionPolicy` as a hypothetical Direct Policy Attachment example in +[GEP-713: Metaresources and PolicyAttachment](../gep-713/index.md). +Because naming is hard, a new name may be +substituted without blocking acceptance of the content of the API change. + +The selection of the applicable Gateway API persona is important in the design of BackendTLSPolicy, because it provides +a way to explicitly describe the _expectations_ of the connection to the application. BackendTLSPolicy is configured +by the application developer Gateway API persona to signal what the application developer _expects_ in connections to +the application, from a TLS perspective. Only the application developer can know what the application expects, so it is +important that this configuration be managed by that persona. + +During the course of discussion of this proposal, we did consider allowing the cluster operator persona to have some access +to Gateway cert validation, but as mentioned, BackendTLSPolicy is used primarily to signal what the application +developer expects in the connection. Granting this expectation to any other role would blur the lines between role +responsibilities, which compromises the role-oriented design principle of Gateway API. As mentioned in Non-goal #8, +providing a mechanism for the cluster operator gateway role to override gateway to backend TLS settings is not covered +by this proposal, but should be addressed in a future update. One idea is to use two types: ApplicationBackendTLSPolicy, +and GatewayBackendTLSPolicy, where the application developer is responsible for the former, the cluster operator is +responsible for the latter, and the cluster operator may configure whether certain settings may be overridden by +application developers. + +The BackendTLSPolicy must contain these configuration items to allow the Gateway to operate successfully +as a TLS Client: + +- An explicit signal that TLS should be used by this connection. +- A hostname the Gateway should use to connect to the backend. +- A reference to one or more certificates to use in the TLS handshake, signed by a CA or self-signed. +- An indication that system certificates may be used. + +BackendTLSPolicy is defined as a Direct Policy Attachment without defaults or overrides, applied to a Service that +accesses the backend in question, where the BackendTLSPolicy resides in the same namespace as the Service it is +applied to. The BackendTLSPolicy and the Service must reside in the same namespace in order to prevent the +complications involved with sharing trust across namespace boundaries. We chose the Service resource as a target, +rather than the Route resource, so that we can reuse the same BackendTLSPolicy for all the different Routes that +might point to this Service. +For the use case where certificates are stored in their own namespace, users may create Secrets and use ReferenceGrants +for a BackendTLSPolicy-to-Secret binding. Implementations must respect a ReferenceGrant for cross-namespace Secret +sharing to BackendTLSPolicy, even if they don't for other cross-namespace sharing. + +One of the areas of concern for this API is that we need to indicate how and when the API implementations should use the +backend destination certificate authority. This solution proposes, as introduced in +[GEP-713](../gep-713/index.md), that the implementation +should watch the connections to the specified TargetRefs (Services), and if a Service matches a BackendTLSPolicy, then +assume the connection is TLS, and verify that the TargetRef’s certificate can be validated by the client (Gateway) using +the provided certificates and hostname before the connection is made. On the question of how to signal +that there was a failure in the certificate validation, this is left up to the implementation to return a response error +that is appropriate, such as one of the HTTP error codes: 400 (Bad Request), 401 (Unauthorized), 403 (Forbidden), or +other signal that makes the failure sufficiently clear to the requester without revealing too much about the transaction, +based on established security requirements. + +All policy resources must include `TargetRefs` with the fields specified +in [PolicyTargetReference](https://github.com/kubernetes-sigs/gateway-api/blob/a33a934af9ec6997b34fd9b00d2ecd13d143e48b/apis/v1alpha2/policy_types.go#L24-L41). +In an upcoming [extension](https://github.com/kubernetes-sigs/gateway-api/issues/2147) to TargetRefs, policy resources +_may_ also choose to include `SectionName` and/or `Port` in the target reference following the same mechanics as `ParentRef`. + +BackendTLSPolicySpec contains the `TargetRefs` and `Validation` fields. The `Validation` field is a +`BackendTLSPolicyValidation` and contains `CACertificateRefs`, `WellKnownCACertificates`, and `Hostname`. +The names of the fields were chosen to facilitate discussion, but may be substituted without blocking acceptance of the +content of the API change. In fact, the `CertRefs` field name was changed to CACertRefs and then to +CACertificateRefs as of April 2024. + +The `CACertificateRefs` and `WellKnownCACertificates` fields are both optional, but one of them must be set for a valid TLS +configuration. CACertificateRefs is an implementation-specific slice of +named object references, each containing a single cert. We originally proposed to follow the convention established by the +[CertificateRefs field on Gateway](https://github.com/kubernetes-sigs/gateway-api/blob/18e79909f7310aafc625ba7c862dfcc67b385250/apis/v1beta1/gateway_types.go#L340) +, but the CertificateRef requires both a tls.key and tls.crt and a certificate reference only requires the tls.crt. +WellKnownCACertificates is an optional enum that allows users to specify whether to use the set of CA certificates trusted by the +Gateway (WellKnownCACertificates specified as "System"), or to use the existing CACertificateRefs (WellKnownCACertificates +specified as ""). The use and definition of system certificates is implementation-dependent, and the intent is that +these certificates are obtained from the underlying operating system. CACertificateRefs contains one or more +references to Kubernetes objects that contain PEM-encoded TLS certificates, which are used to establish a TLS handshake +between the gateway and backend pod. References to a resource in a different namespace are invalid. +If ClientCertificateRefs is unspecified, then WellKnownCACertificates must be set to "System" for a valid configuration. +If WellKnownCACertificates is unspecified, then CACertificateRefs must be specified with at least one entry for a valid configuration. +If WellKnownCACertificates is set to "System" and there are no system trusted certificates or the implementation doesn't define system +trusted certificates, then the associated TLS connection must fail. + +The `Hostname` field is required and is to be used to configure the SNI the Gateway should use to connect to the backend. +Implementations must validate that at least one name in the certificate served by the backend matches this field. +We originally proposed using a list of allowed Subject Alternative Names, but determined that this was [not needed in +the first round](https://github.com/kubernetes-sigs/gateway-api/pull/2113#issuecomment-1696127092), +but may be added in the future. + +We originally proposed allowing the configuration of expected TLS versions, but determined that this was [not needed in +the first round](https://github.com/kubernetes-sigs/gateway-api/pull/2113#issuecomment-1696127092). + +Thus, the following additions would be made to the Gateway API: + +```go +//TODO: Will update this section once API changes from PR 2955 are approved. +``` + +## How a client behaves + +This table describes the effect that a BackendTLSPolicy has on a Route. There are only two cases where the +BackendTLSPolicy will signal a Route to connect to a backend using TLS, an HTTPRoute with a backend that is targeted +by a BackendTLSPolicy, either with or without listener TLS configured. (There are a few other cases where it may be +possible, but is implementation dependent.) + +Every implementation that claims supports for BackendTLSPolicy should document for which Routes it is being implemented. + +| Route Type | Gateway Config | Backend is targeted by a BackendTLSPolicy? | Connect to backend with TLS? | +|------------|----------------------------|-----------------------------------------------|-------------------------------| +| HTTPRoute | Listener tls | Yes | **Yes** | +| HTTPRoute | No listener tls | Yes | **Yes** | +| HTTPRoute | Listener tls | No | No | +| HTTPRoute | No listener tls | No | No | +| TLSRoute | Listener Mode: Passthrough | Yes | No | +| TLSRoute | Listener Mode: Terminate | Yes | Implementation-dependent | +| TLSRoute | Listener Mode: Passthrough | No | No | +| TLSRoute | Listener Mode: Terminate | No | No | +| TCPRoute | Listener TLS | Yes | Implementation-dependent | +| TCPRoute | No listener TLS | Yes | Implementation-dependent | +| TCPRoute | Listener TLS | No | No | +| TCPRoute | No listener TLS | No | No | +| UDPRoute | Listener TLS | Yes | No | +| UDPRoute | No listener TLS | Yes | No | +| UDPRoute | Listener TLS | No | No | +| UDPRoute | No listener TLS | No | No | +| GRPCRoute | Listener TLS | Yes | Implementation-dependent | +| GRPCRoute | No Listener TLS | Yes | Implementation-dependent | +| GRPCRoute | Listener TLS | No | No | +| GRPCRoute | No Listener TLS | No | No | + +## Request Flow + +Step 6 would be changed in the typical client/gateway API request flow for a gateway implemented using a +reverse proxy. This is shown as **bolded** additions in step 6 below. + +1. A client makes a request to http://foo.example.com. +2. DNS resolves the name to a Gateway address. +3. The reverse proxy receives the request on a Listener and uses the Host header to match an HTTPRoute. +4. Optionally, the reverse proxy can perform request header and/or path matching based on match rules of the HTTPRoute. +5. Optionally, the reverse proxy can modify the request, i.e. add/remove headers, based on filter rules of the HTTPRoute. +6. Lastly, the reverse proxy **optionally performs a TLS handshake** and forwards the request to one or more objects, +i.e. Service, in the cluster based on backendRefs rules of the HTTPRoute **and the TargetRefs of the BackendTLSPolicy**. + +## Alternatives +Most alternatives are enumerated in the section "The history of backend TLS". A couple of additional +alternatives are also listed here. + +1. Expand BackendRef, which is already an expansion point. At first, it seems logical that since listeners are handling +the client-gateway certs, BackendRefs could handle the gateway-backend certs. However, when multiple Routes to target +the same Service, there would be unnecessary copying of the BackendRef every time the Service was targeted. As well, +there could be multiple bBackendRefs with multiple rules on a rRoute, each of which might need the gateway-backend cert +configuration, so it is not the appropriate pattern. +2. Extend HTTPRoute to indicate TLS backend support. Extending HTTPRoute would interfere with deployed implementations +too much to be a practical solution. +3. Add a new type of Route for backend TLS. This is impractical because we might want to enable backend TLS on other +route types in the future, and because we might want to have both TLS listeners and backend TLS on a single route. + +## Prior Art + +TLS from gateway to backend for ingress exists in several implementations, and was developed independently. + +### Istio Gateway supports this with a DestinationRule: + +* A secret representing a certificate/key pair, where the certificate is valid for the route host +* Set Gateway spec.servers[].port.protocol: HTTPS, spec.servers[].tls.mode=SIMPLE, spec.servers[].tls.credentialName +* Set DestinationRule spec.trafficPolicy.tls.mode: SIMPLE + +Ref: [Istio / Understanding TLS Configuration](https://istio.io/latest/docs/ops/configuration/traffic-management/tls-configuration/#gateways) +and [Istio / Destination Rule](https://istio.io/latest/docs/reference/config/networking/destination-rule/#ClientTLSSettings) + +### OpenShift Route (comparable to GW API Gateway) supports this with the following route configuration items: + +* A certificate/key pair, where the certificate is valid for the route host +* A separate destination CA certificate enables the Ingress Controller to trust the destination’s certificate +* An optional, separate CA certificate that completes the certificate chain + +Ref: [Secured routes - Configuring Routes | Networking | OpenShift Container Platform 4.12](https://docs.openshift.com/container-platform/4.12/networking/routes/secured-routes.html#nw-ingress-creating-a-reencrypt-route-with-a-custom-certificate_secured-routes) + +### Contour supports this from Envoy to the backend using: + +* An Envoy client certificate +* A CA certificate and SubjectName which are both used to verify the backend endpoint’s identity +* Kubernetes Service annotation: projectcontour.io/upstream-protocol.tls + +Ref: [Upstream TLS](https://projectcontour.io/docs/v1.21.1/config/upstream-tls/) + +### GKE supports a way to encrypt traffic to the backend pods using: + +* `AppProtocol` on Service set to HTTPS +* Load balancer does not verify the certificate used by backend pods + +Ref: [Secure a Gateway](https://cloud.google.com/kubernetes-engine/docs/how-to/secure-gateway#load-balancer-tls) + +### Emissary supports encrypted traffic to services + +* In the `Mapping` definition, set https:// in the spec.service field +* A spec.tls in the `Mapping` definition, with the name of a `TLSContext` +* A `TLSContext` to provide a client certificate, set minimum TLS version support, SNI + +Ref: [TLS Origination](https://www.getambassador.io/docs/emissary/latest/topics/running/tls/origination) + +### NGINX implementation through CRDs (Comparable to Route or Policy of Gateway API) supports both TLS and mTLS + +* In the Upstream section of a VirtualServer or VirtualServerRoute (equivalent to HTTPRoute) there is a simple toggle to enable TLS. This does not validate the certificate of the backend and implicitly trusts the backend in order to form the SSL tunnel. This is not about validating the certificate but obfuscating the traffic with TLS/SSL. +* A Policy attachment can be provided when certification validation is required that is called egressMTLS (egress from the proxy to the upstream). This can be tuned to perform various certificate validation tests. It was created as a Policy because it implies some type of AuthN/AuthZ due to the additional checks. This was also compatible with Open Service Mesh and NGINX Service Mesh and removed the need for a sidecar at the ingress controller. +* A corresponding 'IngressMTLS' policy also exists for mTLS verification of client connections to the proxy. The Policy object is used for anything that implies AuthN/AuthZ. + +Ref: [Upstream.TLS](https://docs.nginx.com/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#upstreamtls) + +Ref: [EgressMTLS](https://docs.nginx.com/nginx-ingress-controller/configuration/policy-resource/#egressmtls) + +Ref: [IngressMTLS](https://docs.nginx.com/nginx-ingress-controller/configuration/policy-resource/#ingressmtls) + +## Answered Questions + +Q. Bowei recommended that we mention the approach of cross-namespace referencing between Route and Service. +Be explicit about using the standard rules with respect to attaching policies to resources. + +A. This is mentioned in the +API section. + +Q. Costin recommended that Gateway SHOULD authenticate with either a JWT with audience or client cert +or some other means - so gateway added headers can be trusted, amongst other things. + +A. This is out of scope for this +proposal, which centers around application developer persona resources such as HTTPRoute and Service. + +Q. Costin mentioned we need to answer the question - is configuring the connection to a backend and TLS +something the route author decides - or the backend owner? + +A. This is decided by the application developer persona, +which would more likely, but not exclusively, be the backend owner. + +Q.Costin continued, same for SAN (Subject Alternative Name) certificates. +The backend owner is the application developer, and the route owner will have to collaborate with the application +developer to provide the appropriate configuration for TLS. The implementation would need to take the certificate +provided by the application and verify that it satisfies the requirements of the route-as-client, including SAN +information. Sometimes the backend owner and route owner are the same entity. + +A. This was most recently addressed by +adding hostname for SNI and removing allowed SANs. + +## Graduation Criteria + +This section is to record issues that were requested for discussion in the API section before this GEP graduates +out of `Provisional` status. + +1. Rob Scott is interested in extending the TargetRef to optionally include port, since we are targeting the entirety +of a Service. See the discussion in https://github.com/kubernetes-sigs/gateway-api/pull/2113/files#r1231594914, +and follow up issue in https://github.com/kubernetes-sigs/gateway-api/issues/2147 +2. Michael Pleshakov asked about conflicts that could arise when multiple implementations are running in a cluster. +This is a gap in our policy attachment model that needs to be addressed. See the discussion in +https://github.com/kubernetes-sigs/gateway-api/pull/2113/files#r1235750540. Graduating this GEP to implementable +requires an update to the Policy GEP to define how status can be nested to support multiple implementations. This will +likely look very similar to Route status. +See [comment](https://github.com/kubernetes-sigs/gateway-api/pull/2113#issuecomment-1696127092). +3. Rob Scott [wanted to note](https://github.com/kubernetes-sigs/gateway-api/pull/2113#issuecomment-1696127092) that +when this graduates to the standard channel, implementations of HTTPRoute may also be +required to watch the BackendTLSPolicy. If one of these policies is attached to a Service targeted by an HTTPRoute, +the implementation would be required to fully implement the policy or mark the backend invalid. + +## References + +[Gateway API TLS Use Cases](https://docs.google.com/document/d/17sctu2uMJtHmJTGtBi_awGB0YzoCLodtR6rUNmKMCs8/edit#heading=h.cxuq8vo8pcxm) + +[GEP-713: Metaresources and PolicyAttachment](../gep-713/index.md) + +[Policy Attachment](../../reference/policy-attachment.md#direct-policy-attachment) + +[Gateway API TLS](../../guides/tls.md) + +[SIG-NET Gateway API: TLS to the K8s.Service/Backend](https://docs.google.com/document/d/1RTYh2brg_vLX9o3pTcrWxtZSsf8Y5NQvIG52lpFcZlo) + +[SAN vs SNI](https://serverfault.com/questions/807959/what-is-the-difference-between-san-and-sni-ssl-certificates) diff --git a/site-src/ko/geps/gep-1897/metadata.yaml b/site-src/ko/geps/gep-1897/metadata.yaml new file mode 100644 index 0000000000..716cf3d042 --- /dev/null +++ b/site-src/ko/geps/gep-1897/metadata.yaml @@ -0,0 +1,15 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1897 +name: BackendTLSPolicy - Explicit Backend TLS Connection Configuration +status: Experimental +authors: + - candita + - brianehlert + - robscott + - youngnick +relationships: + obsoletes: + - number: 1282 + name: Describing Backend Properties + description: Implements just part of the Backend Properties GEP. diff --git a/site-src/ko/geps/gep-1911/index.md b/site-src/ko/geps/gep-1911/index.md new file mode 100644 index 0000000000..c26565ce07 --- /dev/null +++ b/site-src/ko/geps/gep-1911/index.md @@ -0,0 +1,182 @@ +# GEP-1911: Backend Protocol Selection + +* Issue: [#1911](https://github.com/kubernetes-sigs/gateway-api/issues/1911) +* Status: Standard + +(See [status definitions](../overview.md#gep-states).) + +## TLDR + +Not all implementations support automatic protocol selection. Even in some cases protocols are disabled without an explicit opt-in (eg. websockets with Contour & NGINX). Thus application developers need the ability to specify the protocol(s) that their application supports. + +## Goals + +- Support protocols that can have a Gateway `*Route` resource as a frontend +- Standardize Gateway API implementations on the protocols & constants defined by the Kubernetes [Standard Application Protocols (KEP-3726)][kep-3726] +- Support backends with multiple protocols on the same port (ie. tcp/udp) + +## Non-Goals + +- Backend TLS (covered in [GEP-1897](https://github.com/kubernetes-sigs/gateway-api/issues/1897)) +- Additional protocol specific configuration +- Disabling Protocols + +## Introduction + +Since Kubernetes 1.20 the [`core/v1.Service`][k8s-service] and [`core/v1.EndpointSlice`][k8s-endpointslices] resource has a stable `appProtocol` field. It's purpose is to allow end-users to specify an application protocol (L7) for each service port. + +Originally the use of this field in the Gateway API was rejected in [GEP-1282](../gep-1282/index.md#non-goals): +> v1.Service’s appProtocol field is not fit for purpose, because it is defined as accepting values either from the IANA Service Name registry, or domain-prefixed values and we need more flexibility than that. + +Since then a Kubernetes enhancement proposal was created [KEP-3726][kep-3726] to repurpose `appProtocol` to include a convention for protocols that are not IANA service names. This would involve prefixing protocol names with `kubernetes.io/*`. + +Note: Kubernetes will automatically create `EndpointSlices` for `Services` that have a selector. [Custom `EndpointSlices`](https://kubernetes.io/docs/concepts/services-networking/service/#custom-endpointslices) can manually be created. + +## API Semantics + +A Gateway implementation MUST recognize the Kubernetes Standard Application Protocols ([KEP-3726][kep-3726]) for specifying the protocol for a backend reference in a Gateway API `*Route` resource + +Thus when a `*Route` points to a Kubernetes Service, implementations SHOULD honor the appProtocol field if it +is set for the target Service Port. + + +At the moment there exists three defined constants: + +- `kubernetes.io/h2c` - HTTP/2 over cleartext as described in [RFC7540](https://www.rfc-editor.org/rfc/rfc7540) +- `kubernetes.io/ws` - WebSocket over cleartext as described in [RFC6445](https://www.rfc-editor.org/rfc/rfc6455) +- `kubernetes.io/wss` - WebSocket over TLS as described in [RFC6455](https://www.rfc-editor.org/rfc/rfc6455) + +### New Protocols & Reserved Prefix + +To add support for a new protocol it should first become a Kubernetes Standard Application Protocol by updating the [KEP-3726][kep-3726]. [KEP-3726][kep-3726] also states the `appProtocol` field accepts a domain-prefixed implementation specific value. Thus, if the suggested protocol is not suited to have a `kubernetes.io/*` prefix, then the Gateway API MAY support the new protocol using its own prefix `gateway.networking.k8s.io/*`. Please make a PR to this GEP. + +For example we may want to add a sentinel `appProtocol` value that prevents Gateway implementations from discovering the protocol of the application. Instead they should just refer to the Service's `protocol` field. Such a constant was rejected upstream (https://github.com/kubernetes/enhancements/pull/4106) but as an example it could be defined in a future addition to this GEP as `gateway.networking.k8s.io/no-sniff`. + +### Default Protocols + +If a Service `appProtocol` isn't specified an implementation MAY infer the backend protocol through its own means. Implementations MAY infer the protocol from the `Route` type referring to the backend Service. + +Absence of the `appProtocol` field does not imply the implementation should disable any features (eg. websocket upgrades). + +### Multiple Protocols on the Same Port + +Only the Kubernetes `Service` `protocol` field supports multiple protocols on the same port. See the details in [KEP-1435][kep-1435]. + +Implementations MAY support Kubernetes Service BackendRefs that are multiplexing TCP and UDP on the same port. Otherwise implementations MUST set *Route ResolvedRefs condition to False with the "UnsupportedProtocol" Reason with a clear message that multiplexing is not supported. + +Currently Kubernetes `Service` API only allows different `appProtocol` values for the same port when `protocol` fields differs. At this time there seems to be interest in changing `appProtocol` to be a list in order to facilitate this use-case. + +### Supporting Protocols + +If a Route is not able to send traffic to the backend using the specified protocol then the backend is considered invalid. Implementations MUST set `ResolvedRefs` condition to `False` with the Reason `UnsupportedProtocol`. + +Implementations MAY support the following combinations below: + +ServicePort Protocol | ServicePort AppProtocol | Route Type | Supported +-|-|-|- +`TCP` | `kubernetes.io/h2c` | `GRPCRoute` | Yes [1] +`TCP` | `kubernetes.io/h2c` | `HTTPRoute` | Yes +`TCP` | `kubernetes.io/ws` | `HTTPRoute` | Yes +`TCP` | `kubernetes.io/wss` | `TLSRoute` | Yes + +1. GRPC works over h2c - so a GRPCRoute should be able to connect to an h2c backend + +Implementations MAY support the following combinations below: + +ServicePort Protocol | ServicePort AppProtocol | Route Type | Supported +-|-|-|- +ServicePort Protocol | ServicePort AppProtocol | Route Type | Supported +`TCP` | `kubernetes.io/wss` | `HTTPRoute` | Conditional [1] + +1. Only if there is a corresponding `BackendTLSPolicy` - see [GEP-1897](../gep-1897/index.md) + +## Open Questions + +1. TLSRoute & UDP protocol + +TLS over UDP seems to be a thing via QUIC/HTTP3 [ref](https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/). +Likewise there's also [DTLS](https://en.wikipedia.org/wiki/Datagram_Transport_Layer_Security). But it's unclear if Gateway's TLSRoute +applies to an underlying UDP protocol. + +2. Websockets & HTTP/2/3 + +Should we upstream new constants for websocket over [HTTP/2](https://www.rfc-editor.org/rfc/rfc8441.html) & [HTTP/3](https://www.rfc-editor.org/rfc/rfc9220.html) ? HTTP/3 makes things more complicated since its supports UDP as the underlying protocol. + +## Alternatives + +### Single Meta-resource + +The first pass of this GEP proposed a new meta-resource [GEP-713](../gep-713/index.md) called `BackendProtocol`. + +This allows end-users to specify a list of ports and a list of corresponding protocols that that single +port supports. + +This was dropped in favour of supporting Kubernetes Standard Application Protocols. + +### Multiple Protocol Meta-resources + +Rather than bundle protocol details into a single resource an alternative would be to create distinct meta resources. +ie. `HTTP2Backend`, `GRPCBackend`, `WebsocketBackend`. + +The advantages of this approach are: + +- Easy to introduce new protocols +- Definitions/types would be simpler + +The disadvantages of this approach are: + +- N resources for N protocols need to be created to describe a single backend +- No easy mechanic to specify priority of protocols + +### Adding Properties on Gateway Route Objects + +From [GEP-1282](../gep-1282/index.md#tldr): +> some types of configuration requested by users are more about defining functionality that describes capabilities of the backend more than the route you take to get to the backend. + +Backend protocol is specifying capabilities. This configuration is less about routing. + +### Kubernetes Service - Expanding Protocol field + +The `protocol` field on a Kubernetes service is used to specify a L4 protocol over IP. This field isn't appropriate to describe protocols +that operate at a higher 'application' level (eg. HTTP/GRPC etc.) + +### Extending Kubernetes Service + +This is considered untenable due to the 'the turnaround time for those changes can be years.' ([ref-1282](../gep-1282/index.md#non-goals)) + +### Unstructured Data/Special Values + +Unstructured data refers to using labels and annotations. + +From [GEP-1282](../gep-1282/index.md#non-goals): +> these are very sticky and hard to get rid of once you start using them. + +Special values refers to using special strings in existing Kubernetes Resources. +For example Istio allows for protocol to be specified by prefixing the Kubernetes +Service's port name with the protocol (ie. `http-`, `grpc-`). This approach is +limiting as it doesn't allow for multiple protocols on the same port and future +configuration per protocol. One protocol per port may be relaxed in the future see +[KEP 1435][kep-1435] + +Additionally, annotations are not self-documenting unlike CRD fields which can display +documentation via `kubectl explain` + +## References + +- [GitHub Discussion](https://github.com/kubernetes-sigs/gateway-api/discussions/1244) +- GEP-1282 - Describing Backend Properties + - [GEP](../gep-1282/index.md) + - [Issue](https://github.com/kubernetes-sigs/gateway-api/issues/1911) +- [GEP-713 - Metaresources](../gep-713/index.md) +- [Linkerd Protocol Detection](https://linkerd.io/2.12/features/protocol-detection/) +- [Istio Protocol Selection](https://istio.io/latest/docs/ops/configuration/traffic-management/protocol-selection/) +- Contour Protocol Selection + - [Websockets](https://projectcontour.io/docs/1.24/config/websockets/) + - [GRPC](https://projectcontour.io/docs/1.24/guides/grpc/#httpproxy-configuration) +- [AWS Gateway Protocol Selection](https://github.com/aws/aws-application-networking-k8s/blob/a277fb39449383f53cd7d1e5576b4fa190a1a853/config/crds/bases/application-networking.k8s.aws_targetgrouppolicies.yaml#L109) +- [Google GKE AppProtocol Selection](https://cloud.google.com/kubernetes-engine/docs/concepts/ingress-xlb#https_tls_between_load_balancer_and_your_application) + +[k8s-service]: https://kubernetes.io/docs/concepts/services-networking/service/ +[k8s-endpointslices]: https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/ +[kep-3726]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/3726-standard-application-protocols +[kep-1435]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-network/1435-mixed-protocol-lb diff --git a/site-src/ko/geps/gep-1911/metadata.yaml b/site-src/ko/geps/gep-1911/metadata.yaml new file mode 100644 index 0000000000..a3a293c511 --- /dev/null +++ b/site-src/ko/geps/gep-1911/metadata.yaml @@ -0,0 +1,14 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 1911 +name: Backend Protocol Selection +status: Standard +authors: + - dprotaso + - robscott + - frankbu +relationships: + obsoletes: + - number: 1282 + name: Describing Backend Properties + description: Protocol selection was one of the Backend Properties. diff --git a/site-src/ko/geps/gep-2162/index.md b/site-src/ko/geps/gep-2162/index.md new file mode 100644 index 0000000000..38b2dbf60e --- /dev/null +++ b/site-src/ko/geps/gep-2162/index.md @@ -0,0 +1,190 @@ +# GEP-2162: Supported features in GatewayClass Status + +* Issue: [#2162](https://github.com/kubernetes-sigs/gateway-api/issues/2162) +* Status: Experimental + +## TLDR + +This GEP proposes to enhance the [GatewayClassStatus](https://github.com/kubernetes-sigs/gateway-api/blob/f2cd9bb92b4ff392416c40d6148ff7f76b30e649/apis/v1beta1/gatewayclass_types.go#L185) to include a list of Gateway API features supported by the installed GatewayClass. + +## Goals + +* Improve UX by enabling users to easily see what features the implementation (GatewayClass) support. + +* Standardize features and conformance tests names. + +* Automatically run conformance tests based on the supported features populated in GatewayClass status. + +* Provide foundation for tools to block or warn when unsupported features are used. + + +## Non-Goals + +* Validate correctness of supported features published by the implementation. + Meaning we don't intend to verify whether the supported features reported by + the implementation are indeed supported. + + However, the supported features in the status of the GatewayClass should + make it very easy for any individual to run conformance tests against the + GatewayClass using our conformance tooling. + +## Introduction + +The current [GatewayClassStatus](https://github.com/kubernetes-sigs/gateway-api/blob/f2cd9bb92b4ff392416c40d6148ff7f76b30e649/apis/v1beta1/gatewayclass_types.go#L185) is only used to store conditions the controller publishes. + +Partnered with the [Conformance Profiles](https://github.com/kubernetes-sigs/gateway-api/blob/main/geps/gep-1709.md) work, we want to: + +1. Improve UX by enabling users to easily see what features the implementation(GatewayClass) support. +1. Standardize features and conformance tests names. +1. Automatically run conformance tests based on the supported features populated in GatewayClass status. +1. Potentially build tooling to block or warn when unsupported features are used (more under [Future Work](#future-work)). + +This doc proposes to enhance the GatewayClassStatus API so implementations could publish a list of features they support/don't support. + +Implementations **must** publish the supported features before Accepting the GatewayClass, or in the same operation. + +Implementations are free to decide how they manage this information. A common approach could be to maintain static lists of supported features or using predefined sets. + +Note: implementations must keep the published list sorted in ascending alphabetical order. + +## API + +This GEP proposes API changes describes as follow: + +* Update the `GatewayClassStatus` struct to include a string-represented list of `SupportedFeatures`. + + +```go +// GatewayClassStatus is the current status for the GatewayClass. +type GatewayClassStatus struct { + // Conditions is the current status from the controller for + // this GatewayClass. + // + // Controllers should prefer to publish conditions using values + // of GatewayClassConditionType for the type of each Condition. + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // SupportedFeatures is the features the GatewayClass support. + // + // +kubebuilder:validation:MaxItems=64 + SupportedFeatures []string `json:"supportedFeatures,omitempty"` +} +``` + +## Understanding SupportedFeatures field + +Its important to define how we read the list of `SupportedFeatures` we report. + +We have no supported features for core features. If an implementation reports a resource name e.g `HTTPRoute` as a supportedFeature it means it supports all its core features. +In other words, supporting the resource's core features is a requirement for the implementation to say that it supports the resource. + +For Extended/Implementation-specific features we have the supported features names. + +An example of a GatewayClass Status with the SupportedFeatures reported would look like: + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: GatewayClass +... +status: + conditions: + - lastTransitionTime: "2022-11-16T10:33:06Z" + message: Handled by XXX controller + observedGeneration: 1 + reason: Accepted + status: "True" + type: Accepted + supportedFeatures: + - HTTPRoute + - HTTPRouteHostRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + +``` +## Standardize features and conformance tests names + +Before we add the supported features into our API, it is necessary to establish standardized naming and formatting conventions. + +### Formatting Proposal + +#### Feature Names + +Every feature should: + +1. Start with the resource name. i.e HTTPRouteXXX +2. Follow the PascalCase convention. Note that the resource name in the string should come as is and not be converted to PascalCase, i.e HTTPRoutePortRedirect and not HttpRoutePortRedirect. +3. Not exceed 128 characters. +4. Contain only letters and numbers + +#### Conformance test names + +Conformance tests file names should try to follow the `pascal-case-name.go` format. +For example for `HTTPRoutePortRedirect` - the test file would be `httproute-port-redirect.go`. + +We should treat this guidance as "best effort" because we might have test files that check the combination of several features and can't follow the same format. + +In any case, the conformance tests file names should be meaningful and easy to understand. + + +## Followups + +Before we make the changes we need to; + +1. Change the names of the supported features and conformance tests that don't conform with the formatting rules. + + +## Alternatives + +### Re-using ConformanceProfiles structs + +We could use the same structs as we do in conformance profile object, more specifically, the [ProfileReport](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/apis/v1alpha1/profilereport.go#LL24C6-L24C19) struct. + +Though it would be nice to have only one place to update, these structs seems to include much more data relevant to the conformance report but not for our use case. + +That said, conformance profiles are still at experimental stage, we could explore the option to create a shared struct that will be used both for the conformance reports and for the GatewayClass status. + +### Instruct users to read from the future conformance profiles report + +The current plan for conformance profiles is to also include centralized reporting. (more info in [gep-1709](https://github.com/kubernetes-sigs/gateway-api/blob/main/geps/gep-1709.md)) +We could wait for this to be implemented and instruct users to read from that source to determine what features their installed GatewayClass support. + +However, having the supported features published in the GatewayClass Status adds the following values: + +* We could build a mechanism or a tool to block or warn when unsupported features are used. +* Users will be able to select the GatewayClass that suits their needs without having to refer to documentation or conformance reports. + +This does not cover a future piece of work we want to implement which is to warn/block users from applying a Gateway API object if the installed GWC doesn't support it. (originally suggested in [#1804](https://github.com/kubernetes-sigs/gateway-api/issues/1804)). + + +## References + +[discussion #2108](https://github.com/kubernetes-sigs/gateway-api/discussions/2108) +[#1804](https://github.com/kubernetes-sigs/gateway-api/issues/1804) + +## Future Work + +### Research the development of an unsupported feature warning/blocking mechanism +Once the GatewayClass features support are is published into the status we could look into; + +1. Using the supported features in the webhook to validate or block attempts to apply manifests with unsupported features. + + * Developing such mechanism looks like it would have to include cross-resource validation. (checking the GatewayClass while trying to apply a Route for example). This comes with a lot of caveats and we will need consider it carefully. + +2. Build tooling to check and warn when unsupported features are used. + +### Add Gateway API Version field to the GatewayClass Status + +We got some feedback that it will be useful to indicate which Gateway API version the implementation supports. So when we have supported features published in the GatewayClass Status, users will also be able to understand that those are the supported features for a specific Gateway API version. + +This work is likely to require its own small GEP but ideally what this field would mean is that an implementation supports Max(vX.X). + +The value of it is to provide a better user experience and also more foundation for tools to be able to warn for example when a GatewayClass and CRDs have mismatched versions. + +### Add a table with feature name and description to document what each feature means + +Create a comprehensive table detailing feature names and their corresponding descriptions, providing a clear understanding of each feature's purpose and functionality. diff --git a/site-src/ko/geps/gep-2162/metadata.yaml b/site-src/ko/geps/gep-2162/metadata.yaml new file mode 100644 index 0000000000..12b2794aec --- /dev/null +++ b/site-src/ko/geps/gep-2162/metadata.yaml @@ -0,0 +1,10 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 2162 +name: Supported features in GatewayClass Status +status: Experimental +authors: + - LiorLieberman + - robscott + - spacewander + - shaneutt diff --git a/site-src/ko/geps/gep-2257/index.md b/site-src/ko/geps/gep-2257/index.md new file mode 100644 index 0000000000..24cabffa31 --- /dev/null +++ b/site-src/ko/geps/gep-2257/index.md @@ -0,0 +1,200 @@ +# GEP-2257: Gateway API Duration Format + +* Issue: [#2257](https://github.com/kubernetes-sigs/gateway-api/issues/2257) +* Status: Standard + +## TL;DR + +As we extend the Gateway API to have more functionality, we need a standard +way to represent duration values. The first instance is the [HTTPRoute +Timeouts GEP][GEP-1742]; doubtless others will arise. + +[GEP-1742]:../gep-1742/index.md + +## Gateway API Duration Format + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", +"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be +interpreted as described in [RFC 8174]. + +[RFC 8174]:https://datatracker.ietf.org/doc/html/rfc8174 + +A _Gateway API Duration_ or _GEP-2257 Duration_ is a string value that: + +- MUST match the regular expression `^([0-9]{1,5}(h|m|s|ms)){1,4}$` and +- MUST be interpreted as specified by [Golang's `time.ParseDuration`][gotime]. + +Since both of these conditions MUST be true, the effect is that GEP-2257 +Durations are a subset of what `time.ParseDuration` supports: + +- A GEP-2257 Duration MUST be one to four _components_, each of which consists + of an integer _value_ followed immediately by a _unit_. For example, `1h`, + `5m`, `1h5m`, and `1h30m30s500ms` are all valid GEP-2257 Durations. + +- For each component, the value MUST be one to five decimal digits. Floating + point is not allowed. Leading zeroes do not mean octal; the value MUST + always be interpreted as a decimal integer. For example, `1h`, `60m`, `01h`, + and `00060m` are all equivalent GEP-2257 Durations. + +- For each component, the unit MUST be one of `h` (hour), `m` (minute), `s` + (second), or `ms` (millisecond). No units larger than hours or smaller than + milliseconds are supported. + +- The total duration expressed by a GEP-2257 Duration string is the sum of + each of its components. For example, `1h30m` would be a 90-minute duration, + and `1s500ms` would be a 1.5-second duration. + +- There is no requirement that all units must be used. A GEP-2257 Duration of + `1h500ms` is supported (although probably not terribly useful). + +- Units MAY be repeated, although users SHOULD NOT rely on this support since + future revisions of this GEP may remove support for repeated units. If units + are repeated, the total duration remains the sum of all components: a + GEP-2257 duration of `1h2h20m10m` is a duration of 3 hours 30 minutes. + +- Since the value and the unit are both required within a component, `0` is + not a valid GEP-2257 duration string (though `0s` is). Likewise the empty + string is not a valid GEP-2257 duration. + +- Users SHOULD represent the zero duration as `0s`, although they MAY use any + of `0h`, `0m`, etc. Implementations formatting a GEP-2257 Duration for + output MUST render the zero duration as `0s`. + +- The “standard” form of a GEP-2257 Duration uses descending, nonrepeating + units, using the largest unit possible for each component (so `1h` rather + than `60m` or `30m1800s`, and `1h30m` rather than either `90m` or `30m1h`). + Users SHOULD use this standard form when writing GEP-2257 Durations. + Implementations formatting GEP-2257 Durations MUST render them using this + standard form. + + - **Note**: Implementations of Kubernetes APIs MUST NOT modify user input. + For example, implementations MUST NOT normalize `30m1800s` to `1h` in a + CRD `spec`. This "standard form" requirement is limited to instances + where an implementation needs to format a GEP-2257 Duration value for + output. + +A GEP-2257 Duration parser can be easily implemented by doing a regex-match +check before calling a parser equivalent to Go's `time.ParseDuration`. Such +parsers are readily available in (at least) [Go itself][gotime], [Rust's +`kube_core` crate from `kube-rs`][kube-core], and [Python's +`durationpy`][durationpy] package. We expect that these three languages cover +the vast majority of the Kubernetes ecosystem. + +[gotime]:https://pkg.go.dev/time#ParseDuration +[kube-core]:https://docs.rs/kube-core/latest/kube_core/duration/struct.Duration.html +[durationpy]:https://github.com/icholy/durationpy + +## Alternatives + +We considered three main alternatives: + +- Raw Golang `time.ParseDuration` format. This is very widely used in the Go + ecosystem -- however, it is a very open-ended specification and, in + particular, its support for floating-point values and negative durations + makes it difficult to validate. + +- Golang `strfmt.ParseDuration` as used in the APIServer's OpenAPI validation + code. It turns out that `strfmt.ParseDuration` is a superset of + `time.ParseDuration`, so all the problems in validation are still present. + Additionally, `strfmt.ParseDuration` supports day and week units, requiring + discussion of leap seconds. + +- ISO8601/RFC3339 durations. These are considerably less user-friendly than + our proposal: `PT0.5S` is simply not as immediately clear as "500ms". + +There is (a lot) more discussion in [PR 2155]. + +[PR 2155]:https://github.com/kubernetes-sigs/gateway-api/pull/2155 + +## Test Vectors + +### Parsing + +Valid GEP-2257 Duration strings, their canonical forms, and the components of +the resulting durations: + +| Input | Canonical Form | Hours | Minutes | Seconds | Milliseconds | +|-------|-----------------|-------|---------|---------|--------------| +| `0h` | `0s` | 0 | 0 | 0 | 0 | +| `0s` | `0s` | 0 | 0 | 0 | 0 | +| `0h0m0s` | `0s` | 0 | 0 | 0 | 0 | +| `1h` | `1h` | 1 | 0 | 0 | 0 | +| `30m` | `30m` | 0 | 30 | 0 | 0 | +| `10s` | `10s` | 0 | 0 | 10 | 0 | +| `500ms` | `500ms` | 0 | 0 | 0 | 500 | +| `2h30m` | `2h30m` | 2 | 30 | 0 | 0 | +| `150m` | `2h30m` | 2 | 30 | 0 | 0 | +| `7230s` | `2h30s` | 2 | 0 | 30 | 0 | +| `1h30m10s` | `1h30m10s` | 1 | 30 | 10 | 0 | +| `10s30m1h` | `1h30m10s` | 1 | 30 | 10 | 0 | +| `100ms200ms300ms` | `600ms` | 0 | 0 | 0 | 600 | + +Invalid GEP-2257 Duration strings: + +| Input | Reason | +|-------|--------| +| `1` | Missing unit | +| `1m1` | Missing unit | +| `1d` | Days are not supported | +| `1h30m10s20ms50h` | Too many components | +| `999999h` | Too many digits | +| `1.5h` | Floating point is not supported | +| `-15m` | Negative durations are not supported | + +### Formatting + +Valid durations and their canonical GEP-2257 forms: + +| Hours | Minutes | Seconds | Milliseconds | Canonical Form | +|-------|---------|---------|--------------|----------------| +| 0 | 0 | 0 | 0 | `0s` | +| 1 | 0 | 0 | 0 | `1h` | +| 0 | 30 | 0 | 0 | `30m` | +| 0 | 0 | 10 | 0 | `10s` | +| 0 | 0 | 0 | 500 | `500ms` | +| 2 | 30 | 0 | 0 | `2h30m` | +| 1 | 30 | 10 | 0 | `1h30m10s` | +| 0 | 0 | 0 | 600 | `600ms` | +| 2 | 0 | 0 | 600 | `2h600ms` | +| 2 | 30 | 0 | 600 | `2h30m600ms` | +| 2 | 30 | 10 | 600 | `2h30m10s600ms` | +| 0 | 0.5 | 0 | 0 | `30s` | +| 0 | 0 | 0.5 | 0 | `500ms` | +| 10 days | 0 | 0 | 0 | `240h` | + +Note the last three durations: while `0.5m`, for example, is not a valid +GEP-2257 Duration, it is possible to express a half-minute duration using +GEP-2257. Implementations that support formatting durations SHOULD support +these cases and, if they do, MUST always format them as valid GEP-2257 +Durations. + +Note also that, as stated above, implementations MUST NOT modify resources +supplied by a user. The formatting vectors above describe correctness when an +implementation needs to format a duration for output; no requirement to +normalize user input is implied. + +Invalid durations: + +| Duration | Reason | +|----------|--------| +| 100 microseconds | Sub-millisecond precision is not supported | +| 0.5 milliseconds | Sub-millisecond precision is not supported | +| 10000 days | Out of range (more than 99999 hours) | +| -15 minutes | Negative durations are not supported | + +## Graduation Criteria + +To graduate GEP-2257 to Standard channel, we need to meet the following +criteria: + +- Publish a set of test vectors for the GEP-2257 duration format. + +- Have Go, Rust, and Python implementations of the parser, with a test suite + covering all the test vectors. + +- Have a custom CEL validator for GEP-2257 Duration fields. + +The previous graduation criterion of "Have support for GEP-2257 Durations in +standard Kubernetes libraries" has been removed. Work is in progress to add +such parsers to `kube-rs`, `client-go`, and `client-python`, but it is not +necessary to gate the graduation of GEP-2257 on this work. diff --git a/site-src/ko/geps/gep-2257/metadata.yaml b/site-src/ko/geps/gep-2257/metadata.yaml new file mode 100644 index 0000000000..ea046a3b69 --- /dev/null +++ b/site-src/ko/geps/gep-2257/metadata.yaml @@ -0,0 +1,18 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 2257 +name: Gateway API Duration Format +status: Standard +authors: + - kflynn +relationships: + seeAlso: + - number: 1742 + name: HTTPRoute Timeouts + description: HTTPRoute Timeouts use the format specified in this GEP. +references: + - https://datatracker.ietf.org/doc/html/rfc8174 + - https://datatracker.ietf.org/doc/html/rfc2119 + - https://github.com/kubernetes-sigs/gateway-api/pull/2155 +changelog: + - https://github.com/kubernetes-sigs/gateway-api/pull/3210 diff --git a/site-src/ko/geps/gep-2648/index.md b/site-src/ko/geps/gep-2648/index.md new file mode 100644 index 0000000000..96366db784 --- /dev/null +++ b/site-src/ko/geps/gep-2648/index.md @@ -0,0 +1,494 @@ +# GEP-2648: Direct Policy Attachment + +* Issue: [#2648](https://github.com/kubernetes-sigs/gateway-api/issues/2648) +* Status: Provisional + +(See [status definitions](../overview.md#gep-states).) + +## TLDR + +Describe and specify a design pattern for a class of metaresource that can +affect specific settings across a single target object. + +This is a strict subset of all Policy objects that meet a set of criteria +designed to be easier to understand for users than Inherited Policy, and so to +not require solving the much harder problem of communicating Inherited Policy +to users. + +This will allow the graduation of this _limited_ subcategory of Policy objects +_separately_ to solving the larger problem of communicating status for Inherited +Policy. + +This is a design for a _pattern_, not an API field or new object. + +!!! danger + This GEP is in the process of being updated. + Please see the discussion at https://github.com/kubernetes-sigs/gateway-api/discussions/2927 + and expect further changes. + Some options under discussion there may make the distinction between Direct + and Inherited Policies moot, which would require a rework. + +## Goals + +* Specify what common properties all Direct Attached Policies MUST have +* Recommend design patterns for areas that cannot be mandated but that could + cause problems for API designers. + +## Non-Goals + +* Fully specify the entire design space for Direct Policy Attachment + +## Introduction + +GEP-713 defines two classes of Policy Attachment: Direct and Inherited. + +Direct Attached Policies (or Direct Policies) _only_ affect the object they are +attached to; that is, the object specified in their `targetRef`. + +Note that as soon as the Policy affects more objects than the referenced object, +it is an Inherited Policy. + +## Direct Policy Attachment requirements in brief + +The following parts of GEP-713 also apply here. Direct Policy Attachments: + +- MUST be their own CRDs (e.g. `TimeoutPolicy`, `RetryPolicy` etc), +- MUST include both `spec` and `status` stanzas +- MUST have the `status` stanza include a `conditions` section using the standard + upstream Condition type. This includes using reasons such as `Conflicted` (for + when a Policy cannot be accepted because another Policy is targeting the same + object) or `TargetNotFound` when the Policy targets a nonexistent object. +- MUST use the `targetRef` struct to specify their target resource. +- MUST follow the naming requirements (MUST be named to clearly indicate that the +kind is a Policy, and SHOULD use the `Policy` suffix at the end of the Kind and +`policies` at the end of the Resource names). +- MAY target a subsection of a resource using the `sectionName` field of the + `targetRef` struct. If it does, it MUST abide by the rules in this document, + and MUST clearly indicate the objects that `sectionName` may be used on in its + documentation. + +## Direct Policy Attachment + +A Direct Policy Attachment is tightly bound to one instance of a particular +Kind within a single namespace (or to an instance of a single Kind at cluster scope), +and only modifies the behavior of the object that matches its binding. + +As an example, the BackendTLSPolicy is specified in [GEP-1897](../gep-1897/index.md), +BackendTLSPolicy - Explicit Backend TLS Connection Configuration. This Policy +attaches to the Service object and tells Gateway API implementations what TLS +settings should be used to connect to that Service when it is used as a backend +by a Route. + +See GEP-1897 for all the details of this Policy object. + +## Direct Policy design rules + +In these rules, "affects" means to change properties of an object that are +relevant in objects that are stored in the storage medium of the objects in the +hierarchy. If the combination of objects in the object hierarchy cause the creation +of some other object in the object store (usually, the Kubernetes API), +differences in that object do not count as "affecting" for the purposes of these +rules. For example, if you take a GatewayClass -> Gateway -> Route +-> Service hierarchy, and attach a Policy somewhere, which leads to the creation +of a DataplaneConfig object that will be different because of the inclusion of +the Policy object, the DataplaneConfig object does not affect if the Policy is +a Direct one or not. This is because _a user can understand the state of the +hierarchy by looking at all the objects in the hierarchy_. DataplaneConfig is +_outside_ the hierarchy in terms of understanding the state of the Policy. +Direct Attached Policy is intended as a way to _manage the complexity_ of +Policy objects and allow a _limited_ set of Policies to follow vastly more +simple design patterns _if they meet a set of criteria_. + +With that background and the previous example in mind, here are some rules for +when a Policy is a Direct Attached Policy: + +* The Policy can only be attached at exactly _one_ layer in the hierarchy. Any Policy + that can be attached at multiple levels must necessarily have some defaulting + behavior in the case that two of the same kind are attached at different points + in the same hierarchy, so it cannot be Direct. +* The Policy can have effects only at the layer it attaches to. That is, the + behavior modifications MUST only affect the single object that the targeted + metaresource is bound to, and MUST NOT have ramifications that flow beyond that + object. No attaching a Policy to a Gateway and affecting settings in Routes or + backends. If a Direct Attached Policy attaches to an object, it can only affect + properties _of that object_ and _at that layer_ of the hierarchy. +* The Policy can have effects only on the object it attaches to within the layer + of the hierarchy it attaches to. A Direct Attached Policy cannot affect sibling + objects in the same hierarchy directly. +* In terms of status, it SHOULD be reasonably easy for a user to understand that + everything is working - basically, as long as the targeted object exists, + the modifications are valid, the metaresource is valid, and this should be + straightforward to communicate in one or two Conditions. The `status` stanza + in BackendTLSPolicy is an example of one of the recommended ways to achieve this. +* Direct Policy Attachment SHOULD only be used to target objects in the same + namespace as the Policy object. Allowing cross-namespace references brings in + significant security concerns, and/or difficulties about merging cross-namespace + policy objects. Notably, Mesh use cases may need to do something like this for + consumer policies, but in general, Policy objects that modify the behavior of + things outside their own namespace should be avoided unless it uses a handshake + of some sort, where the things outside the namespace can opt–out of the behavior. + (Notably, this is the design that we used for ReferenceGrant). + +## Target References +### Cross Namespace + +In all cases, Gateway API policies should only have an effect on the namespace +they exist within. In the case of policies that could apply to mesh +implementations, it may be desirable to have a policy that affects traffic +originating from the local namespace but going to a separate namespace. Unless +that specific case is desired, all policy target refs should be local and +exclude the "namespace" field. + +### Multiple + +In some cases, it may be desirable for a policy to target more than one resource +at a time. For example, a policy may apply to different variations of what is +effectively the same Service (store, store-blue, and store-green). If this is +desired, a policy can choose to support a `targetRefs` list instead of a +singular `targetRef` field. This list can have a maximum of 16 entries, though +it may be desirable to start with a lower limit depending on the policy. + +#### Migration from Single to Multiple Targets + +Existing policies with a single `targetRef` may want to transition to supporting +multiple `targetRefs`. To accomplish this, we recommend adding CEL validation +to your CRD to allow only one of the fields to be set. Users will be able to +set `targetRefs` in the same update that they unset `targetRef`. + +### Section Names + +The `sectionName` field of `targetRef` can be used to target a specific section +of other resources, for example: + +* Service.Ports.Name +* Gateway.Listeners.Name +* HTTPRoute.Rules.Name (once they are added in [GEP-995](../gep-995/index.md), implementation tracked by [#2985](https://github.com/kubernetes-sigs/gateway-api/pull/2985)) + +Implementations SHOULD NOT use the name of a `backendRef` for applying Policy, +since the `backendRef` both is not guaranteed to be unique across a Route's rules, +and also the `backendRef` is also a link to another object. Target the policy +at the thing the `backendRef` points to instead. + +For example, the RetryPolicy below applies to a RouteRule inside an HTTPRoute. +(or rather, it will when GEP-995 merges). + +```yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: http-app-1 + labels: + app: foo +spec: + hostnames: + - "foo.com" + rules: + - name: bar + matches: + - path: + type: Prefix + value: /bar + backendRefs: + - name: my-service1 + port: 8080 +--- +apiVersion: networking.acme.io/v1alpha2 +kind: RetryPolicy +metadata: + name: foo +spec: + maxRetries: 5 + targetRef: + name: http-app-1 + group: gateway.networking.k8s.io + kind: HTTPRoute + sectionName: bar +``` + +If a `sectionName` is specified, but does not exist on the targeted object, the +Policy must fail to attach, and the policy implementation should record a +`resolvedRefs` failure or similar Condition in the Policy's status. + +When multiple Policies of the same type target the same object, one with a +`sectionName` and one without, the more specific policy (i.e., the one with a +`sectionName`) will have its entire `spec` applied to the named section. +The less specific policy will also have its `spec` applied to the target but +MUST not affect the named section. The less specific policy will have its `spec` +applied to all other sections of the target that are not targeted by any other +more specific policies. + +When more than one object matches the same object _and_ `sectionName`, the usual +conflict-resolution rules (as defined in GEP-713 should be used). These boil down +to "oldest by creation date wins". + +## User discoverability and status + +### Standard label on CRD objects + +Each CRD that defines a Direct Policy object MUST include a label that specifies that +it is a Policy object, and that label MUST specify that the object is a `direct` +one. + +The label is `gateway.networking.k8s.io/policy: direct`. + +This solution is intended to allow both users and tooling to identify which CRDs +in the cluster should be treated as Policy objects, and so is intended to help +with discoverability generally. It will also be used by the forthcoming `kubectl` +plugin. + +### Conditions + +Implementations using Policy objects MUST include a `spec` and `status` stanza, +and the `status` stanza MUST contain a `conditions` stanza, using the standard +Condition format. + +Policy authors should consider namespacing the `conditions` stanza with a +`controllerName`, as in Route status, if more than one implementation will be +reconciling the Policy type. + +#### On `Policy` objects + +Each Direct Attached Policy MUST populate the `Accepted` condition and reasons +as defined in the PolicyCondition API, a snapshot of which is included below. +The canonical representation is in the actual Go files. (At the time of writing, +this is in `apis/v1alpha2/policy_types.go`) + +```go +// PolicyConditionType is a type of condition for a policy. +type PolicyConditionType string + +// PolicyConditionReason is a reason for a policy condition. +type PolicyConditionReason string + +const ( + // PolicyConditionAccepted indicates whether the policy has been accepted or rejected + // by a targeted resource, and why. + // + // Possible reasons for this condition to be True are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "Conflicted" + // * "Invalid" + // * "TargetNotFound" + // + PolicyConditionAccepted PolicyConditionType = "Accepted" + + // PolicyReasonAccepted is used with the "Accepted" condition when the policy has been + // accepted by the targeted resource. + PolicyReasonAccepted PolicyConditionReason = "Accepted" + + // PolicyReasonConflicted is used with the "Accepted" condition when the policy has not + // been accepted by a targeted resource because there is another policy that targets the same + // resource and a merge is not possible. + PolicyReasonConflicted PolicyConditionReason = "Conflicted" + + // PolicyReasonInvalid is used with the "Accepted" condition when the policy is syntactically + // or semantically invalid. + PolicyReasonInvalid PolicyConditionReason = "Invalid" + + // PolicyReasonTargetNotFound is used with the "Accepted" condition when the policy is attached to + // an invalid target resource + PolicyReasonTargetNotFound PolicyConditionReason = "TargetNotFound" +) +``` + +#### On targeted resources + +Implementations that use Direct Policy objects SHOULD put a Condition into +`status.Conditions` of any objects affected by a Direct Policy, if that field +is present. Ideally, there should be a set of Conditions that can be namespaced +by the implementing controller, but if that is not possible, use the guidance below. + +If they do, that Condition MUST have a `type` ending in `PolicyAffected` (like +`gateway.networking.k8s.io/PolicyAffected`), +and have the optional `observedGeneration` field kept up to date when the `spec` +of the Policy-attached object changes. + +Implementations SHOULD use their own unique domain prefix for this Condition +`type` - it is recommended that implementations use the same domain as in the +`controllerName` field on GatewayClass (or some other implementation-unique +domain for implementations that do not use GatewayClass). + +For objects that do _not_ have a `status.Conditions` field available (`Secret` +is a good example), that object SHOULD instead have a label of +`gateway.networking.k8s.io/PolicyAffected: true` (or with an +implementation-specific domain prefix) added instead. + +Because these Conditions or labels are namespaced per-implementation, +implementations SHOULD: + +- Add the Condition or label if an object is policy affected when it is not + already present +- Remove the Condition or label when the last policy object stops referencing + the targeted object. + +### Other Status designs + +This section contains other recommendations for status designs. Note that this +is a SHOULD rather than a MUST, as this design is still not final. + + +#### Standard status struct + +This design is not final and we invite feedback on any use of it in implementations. + +Policy objects SHOULD use the upstream `PolicyAncestorStatus` struct in their +respective Status structs. Please see the included `PolicyAncestorStatus` struct, +and its use in the `BackendTLSPolicy` object for detailed examples. Included here +is a representative version. + +This pattern enables different conditions to be set for different "Ancestors" +of the target resource. This is particularly helpful for policies that may be +implemented by multiple controllers or attached to resources with different +effects or capabilities. For example a Policy that could attach to Route or Service +to set load balancing properties may be reconciled by multiple controllers, and +so needs further namespacing of its status. This pattern also provides a clear +view of what resources a policy is affecting. + +For the best integration with community tooling and consistency across +the broader community, we recommend that all implementations transition +to Policy status with this kind of nested structure. + +This is an `Ancestor` status rather than a `Parent` status, as in the Route status +because for Policy attachment, the relevant object may or may not be the direct +parent. + +For example, `BackendTLSPolicy` directly attaches to a Service, which may be included +in multiple Routes, in multiple Gateways. However, for many implementations, +the status of the `BackendTLSPolicy` will be different only at the Gateway level, +so Gateway is the relevant Ancestor for the status. + +Each Gateway that has a Route that includes a backend with an attached `BackendTLSPolicy` +MUST have a separate `PolicyAncestorStatus` section in the `BackendTLSPolicy`'s +`status.ancestors` stanza, which mandates that entries must be distinct using the +combination of the `AncestorRef` and the `ControllerName` fields as a key. + +See [GEP-1897][gep-1897] for the exact details. A snapshot of the Go code is +included here for reference, but the canonical representation is in the code +itself (at the time of writing, this is in `apis/v1alpha2/policy_types.go`). + +[gep-1897]: ../gep-1897/index.md + +```go +// PolicyAncestorStatus describes the status of a route with respect to an +// associated Ancestor. +// +// Ancestors refer to objects that are either the Target of a policy or above it in terms +// of object hierarchy. For example, if a policy targets a Service, an Ancestor could be +// a Route or a Gateway. + +// In the context of policy attachment, the Ancestor is used to distinguish which +// resource results in a distinct application of this policy. For example, if a policy +// targets a Service, it may have a distinct result per attached Gateway. +// +// Policies targeting the same resource may have different effects depending on the +// ancestors of those resources. For example, different Gateways targeting the same +// Service may have different capabilities, especially if they have different underlying +// implementations. +// +// For example, in BackendTLSPolicy, the Policy attaches to a Service that is +// used as a backend in a HTTPRoute that is itself attached to a Gateway. +// In this case, the relevant object for status is the Gateway, and that is the +// ancestor object referred to in this status. +// +// Note that a Target of a Policy is also a valid Ancestor, so for objects where +// the Target is the relevant object for status, this struct SHOULD still be used. +type PolicyAncestorStatus struct { + // AncestorRef corresponds with a ParentRef in the spec that this + // RouteParentStatus struct describes the status of. + AncestorRef ParentReference `json:"ancestorRef"` + + // ControllerName is a domain/path string that indicates the name of the + // controller that wrote this status. This corresponds with the + // controllerName field on GatewayClass. + // + // Example: "example.net/gateway-controller". + // + // The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + // valid Kubernetes names + // (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + // + // Controllers MUST populate this field when writing status. Controllers should ensure that + // entries to status populated with their ControllerName are cleaned up when they are no + // longer necessary. + ControllerName GatewayController `json:"controllerName"` + + // Conditions describes the status of the Policy with respect to the given Ancestor. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + + +// PolicyStatus defines the common attributes that all Policies SHOULD include +// within their status. +type PolicyStatus struct { + // Ancestors is a list of ancestor resources (usually Gateways) that are + // associated with the route, and the status of the route with respect to + // each ancestor. When this route attaches to a parent, the controller that + // manages the parent and the ancestors MUST add an entry to this list when + // the controller first sees the route and SHOULD update the entry as + // appropriate when the relevant ancestor is modified. + // + // Note that choosing the relevant ancestor is left to the Policy designers; + // an important part of Policy design is designing the right object level at + // which to namespace this status. + // + // Note also that implementations MUST ONLY populate ancestor status for + // the Ancestor resources they are responsible for. Implementations MUST + // use the ControllerName field to uniquely identify the entries in this list + // that they are responsible for. + // + // A maximum of 32 ancestors will be represented in this list. An empty list + // means the Policy is not relevant for any ancestors. + // + // +kubebuilder:validation:MaxItems=32 + Ancestors []PolicyAncestorStatus `json:"ancestors"` +} +``` + +## Examples + +### Hypothetical TLSMinimumVersionPolicy + +The following hypothetical Policy sets the minimum TLS version required on a +Gateway Listener: + +```yaml +apiVersion: networking.example.io/v1alpha1 +kind: TLSMinimumVersionPolicy +metadata: + name: minimum12 + namespace: appns + labels: + "gateway.networking.k8s.io/policy": "direct" +spec: + minimumTLSVersion: 1.2 + targetRef: + name: internet + group: gateway.networking.k8s.io + kind: Gateway +``` + +Note that because there is no version controlling the minimum TLS version in the +Gateway `spec`, this is an example of a non-field Policy. + +This is an example of a Direct Attached Policy because it affects a field on the +Gateway itself, rather than fields or behavior associated with Routes attached +to that Gateway. + +### BackendTLSPolicy + +BackendTLSPolicy, introduced in [GEP-1897](../gep-1897/index.md) +allows backends to set the TLS details that a Gateway implementation must use +to connect to that backend. + +It does this using a Direct Attached Policy that attaches to a Service. + +Work on this Policy is still ongoing, please see GEP-1897 for details. diff --git a/site-src/ko/geps/gep-2648/metadata.yaml b/site-src/ko/geps/gep-2648/metadata.yaml new file mode 100644 index 0000000000..7e9b54a867 --- /dev/null +++ b/site-src/ko/geps/gep-2648/metadata.yaml @@ -0,0 +1,23 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 2648 +name: Direct Policy Attachment +status: Provisional +# Any authors who contribute to the GEP in any way should be listed here using +# their GitHub handle. +authors: + - youngnick + - robscott +relationships: + extends: + - name: Metaresources and Policy Attachment + number: 713 + description: Split out Direct Policy Attachment into its own GEP +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: + - "https://github.com/kubernetes-sigs/gateway-api/discussions/2927" +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: + - "https://github.com/kubernetes-sigs/gateway-api/pull/2813" diff --git a/site-src/ko/geps/gep-2649/2649-hierarchy.png b/site-src/ko/geps/gep-2649/2649-hierarchy.png new file mode 100644 index 0000000000..77c15e12ee Binary files /dev/null and b/site-src/ko/geps/gep-2649/2649-hierarchy.png differ diff --git a/site-src/ko/geps/gep-2649/2649-ingress-complex.png b/site-src/ko/geps/gep-2649/2649-ingress-complex.png new file mode 100644 index 0000000000..2bb3e2541d Binary files /dev/null and b/site-src/ko/geps/gep-2649/2649-ingress-complex.png differ diff --git a/site-src/ko/geps/gep-2649/2649-ingress-simple.png b/site-src/ko/geps/gep-2649/2649-ingress-simple.png new file mode 100644 index 0000000000..62a2317db9 Binary files /dev/null and b/site-src/ko/geps/gep-2649/2649-ingress-simple.png differ diff --git a/site-src/ko/geps/gep-2649/2649-mesh-complex.png b/site-src/ko/geps/gep-2649/2649-mesh-complex.png new file mode 100644 index 0000000000..c1a12fd36b Binary files /dev/null and b/site-src/ko/geps/gep-2649/2649-mesh-complex.png differ diff --git a/site-src/ko/geps/gep-2649/2649-mesh-simple.png b/site-src/ko/geps/gep-2649/2649-mesh-simple.png new file mode 100644 index 0000000000..5ab39b567a Binary files /dev/null and b/site-src/ko/geps/gep-2649/2649-mesh-simple.png differ diff --git a/site-src/ko/geps/gep-2649/2649-policy-hierarchy.png b/site-src/ko/geps/gep-2649/2649-policy-hierarchy.png new file mode 100644 index 0000000000..593543d2df Binary files /dev/null and b/site-src/ko/geps/gep-2649/2649-policy-hierarchy.png differ diff --git a/site-src/ko/geps/gep-2649/index.md b/site-src/ko/geps/gep-2649/index.md new file mode 100644 index 0000000000..dbcc73f78a --- /dev/null +++ b/site-src/ko/geps/gep-2649/index.md @@ -0,0 +1,785 @@ +# GEP-2649: Inherited Policy Attachment + +* Issue: [#2649](https://github.com/kubernetes-sigs/gateway-api/issues/2649) +* Status: Experimental + +(See [status definitions](../overview.md#gep-states).) + +## TLDR + +Describe and specify a design pattern for a class of metaresource that can +affect specific settings across a multiple target objects. + +This is a design for a _pattern_, not an API field or new object. + +!!! danger + This GEP is in the process of being updated. + Please see the discussion at https://github.com/kubernetes-sigs/gateway-api/discussions/2927 + and expect further changes. + Some options under discussion there may make the distinction between Direct + and Inherited Policies moot, which would require a rework. + +## Goals + +* Specify what common properties all Inherited Policies MUST have +* Recommend design patterns for areas that cannot be mandated but that could + cause problems for API designers. + +## Non-Goals + +* Fully specify the entire design space for Inherited Policy Attachment + +## Inherited Policy Attachment requirements in brief + +The following parts of GEP-713 also apply here. Inherited Policy Attachments: + +- MUST be their own CRDs (e.g. `TimeoutPolicy`, `RetryPolicy` etc), +- MUST include both `spec` and `status` stanzas +- MUST have the `status` stanza include a `conditions` section using the standard + upstream Condition type +- MUST use the `targetRef` struct to specify their target resource. +- MUST follow the naming requirements (MUST be named to clearly indicate that the +kind is a Policy, and SHOULD use the `Policy` suffix at the end of the Kind and +`policies` at the end of the Resource names). + +Additionally, Inherited Policy Attachment: + +- MAY specify a `defaults` stanza, an `overrides` stanza, or both. If it does not, + it MUST specify if its fields are defaults or overrides in each field's godoc. + +## Inherited Policy Attachment + +Because a Inherited Policy is a metaresource, it targets some other resource +and _augments_ its behavior. + +But why have this distinct from other types of metaresource? Because Inherited +Policy resources are designed to have a way for settings to flow down a hierarchy. + +_Any_ object that affects settings outside of the object that it attaches to is +an Inherited Policy. + +Note that the same object may be have some properties of both an Inherited Policy +_and_ a Direct Policy if it can attach to multiple points of a hierarchy, such +as if the same Policy can be attached to a Gateway (where it affects all Routes +attached to that Gateway) or to a Route (where it affects only that Route). + +If a Policy _can be_ used as an Inherited Policy, it MUST be treated as an +Inherited Policy, regardless of whether a specific instance of the Policy is +only affecting a single object. + +This is because all of the rules about inheritance apply to the object, regardless +of where it is attached in the hierarchy. + +Regardless of exactly how they are designed, settings in an Inherited Policy +generally fall into two categories, Defaults and Overrides. + +Defaults set the default value for something, and can be overridden by the +“lower” objects (like a connection timeout default policy on a Gateway being +overridable inside a HTTPRoute), and Overrides cannot be overridden by “lower” +objects (like setting a maximum client timeout to some non-infinite value at the +Gateway level to stop HTTPRoute owners from leaking connections over time). + +Note that while both types of setting are valid, both also come with difficulties +in communicating the currently active setting to the owners of the modified +objects. These are discussed in more detail below. + +## Inherited Policy design guidelines + +Here are some guidelines for when to consider using a Inherited Policy object: + +* The settings or configuration are bound to one containing object, but affect + other objects attached to that one (for example, affecting HTTPRoutes attached + to a single Gateway, or all HTTPRoutes in a GatewayClass). +* The settings need to able to be defaulted, but can be overridden on a per-object + basis. +* The settings must be enforced by one persona, and not modifiable or removable + by a lesser-privileged persona. (For example, The owner of a GatewayClass may + want to restrict something about all Gateways in a GatewayClass, regardless of + who owns the Gateway, or a Gateway owner may want to enforce some setting + across all attached HTTPRoutes). +* In terms of status, a good accounting for how to record that the Policy is + attached is easy, but recording what resources the Policy is being applied to + is not, and needs to be carefully designed to avoid fanout apiserver load. + +When multiple Inherited Policies are used, they can interact in various ways, +which are governed by the following rules, which will be expanded on later in +this document. + +* If a Policy does not affect an object's fields directly, then the resultant + Policy MUST be the set of all distinct fields inside the relevant Policy objects, + as set out by the rules below. +* For Policies that affect an object's existing fields, multiple instances of the + same Policy Kind affecting an object's fields MUST be evaluated as + though only a single Policy "wins" the right to affect each field. This operation + is performed on a _per-distinct-field_ basis. +* Settings in `overrides` stanzas MUST win over the same setting in a `defaults` + stanza. +* `overrides` settings operate in a "less specific beats more specific" fashion - + Policies attached _higher_ up the hierarchy beat the same type of Policy + attached further down the hierarchy. +* `defaults` settings operate in a "more specific beats less specific" fashion - + Policies attached _lower down_ the hierarchy beat the same type of Policy + attached further _up_ the hierarchy. +* For `defaults`, the _most specific_ value is the one _inside the object_ that + the Policy applies to; that is, if a Policy specifies a `default`, and an object + specifies a value, the _object's_ value wins. +* When Policies interact with _fields_ in other objects (for example, if they + set a default or override for a field in a HTTPRoute), they MUST do so in a + "replace value" fashion. + * For fields where the `value` is a scalar, (like a string or a number) + MUST have their value _replaced_ by the value in the Policy if it wins. + Notably, this means that a `default` will only ever replace an empty or unset + value in an object. Note also that, as in Go, the empty string value is _only_ + a string of length 0, generally represented as `""`. + * For fields where the value is an object, the Policy should include the fields + in the object in its definition, so that the replacement can be performed + on each field inside the object as a simple field rather than the object as + a whole. + * For fields where the final value is non-scalar, but is not an _object_ with + fields of its own, the value MUST be entirely replaced, _not_ merged. This + means that lists of strings or lists of ints specified in a Policy overwrite + the empty list (in the case of a `default`) or any specified list (in the case + of an `override`). The same applies to `map[string]string` fields. An example + here would be a field that stores a map of annotations - specifying a Policy + that overrides annotations will mean that a final object specifying those + annotations will have its value _entirely replaced_ by an `override` setting. +* In the case that two Policies of the same type specify different fields, then + _all_ of the specified fields MUST take effect on the affected object, using + the precedence rules given above. + +Examples to further illustrate these rules are given below. + +#### Attaching Policy to GatewayClass +GatewayClass may be the trickiest resource to attach policy to. Policy +attachment relies on the policy being defined within the same scope as the +target. This ensures that only users with write access to a policy resource in a +given scope will be able to modify policy at that level. Since GatewayClass is a +cluster scoped resource, this means that any policy attached to it must also be +cluster scoped. + +GatewayClass parameters provide an alternative to policy attachment that may be +easier for some implementations to support. These parameters can similarly be +used to set defaults and requirements for an entire GatewayClass. + +### Merging into existing `spec` fields + +It's possible (even likely) that configuration in a Policy may need to be merged +into an existing object's fields somehow, particularly for Inherited policies. + +When merging into an existing fields inside an object, Policy objects should +merge values at a scalar level, not at a struct or object level. + +For example, in the `CDNCachingPolicy` example below, the `cdn` struct contains +a `cachePolicy` struct that contains fields. If an implementation was merging +this configuration into an existing object that contained the same fields, it +should merge the fields at a scalar level, with the `includeHost`, +`includeProtocol`, and `includeQueryString` values being defaulted if they were +not specified in the object being controlled. Similarly, for `overrides`, the +values of the innermost scalar fields should overwrite the scalar fields in the +affected object. + +Implementations should not copy any structs from the Policy object directly into the +affected object, any fields that _are_ overridden should be overridden on a per-field +basis. + +In the case that the field in the Policy affects a struct that is a member of a list, +each existing item in the list in the affected object should have each of its +fields compared to the corresponding fields in the Policy. + +For non-scalar field _values_, like a list of strings, or a `map[string]string` +value, the _entire value_ must be overwritten by the value from the Policy. No +merging should take place. This mainly applies to `overrides`, since for +`defaults`, there should be no value present in a field on the final object. + +There is one exception here: the listMapType list. These are lists of structs +that, in their API definitions, define one string in the struct as a key, and +are defined to be treated the same as a map (only one entry for each value in +the key can be present, and patches that duplicate the key overwrite the rest +of the struct). + +For these values, and these values _only_, implementations SHOULD treat the list +like a map and merge values into the corresponding entry, by the key field. + +This table shows how this works for various types: + +|Type|Object config|Override Policy config|Result| +|----|-------------|----------------------|------| +|string| `key: "foo"` | `key: "bar"` | `key: "bar"` | +|list| `key: ["a","b"]` | `key: ["c","d"]` | `key: ["c","d"]` | +|`map[string]string`| `key: {"foo": "a", "bar": "b"}` | `key: {"foo": "c", "bar": "d"}` | `key: {"foo": "c", "bar": "d"}` | +|listMapType| `listMaps: [{"name": "o1", "foo": "a", "bar": "b"},{"name": "o2", "foo": "c", "bar": "d"}]` | `listMaps: [{"name": "o1", "foo": "e", "bar": "f", "baz": "g"}]` | `listMaps: [{"name": "o1", "foo": "e", "bar": "f", "baz": "g"},{"name": "o2", "foo": "c", "bar": "d"}]` | + + +### Conflict Resolution + +Other conflict resolution between Policy objects must also follow the rules +outlined in GEP-713, in its Conflict Resolution section. + +## Policy Attachment examples and behavior + +This approach is building on concepts from all of the alternatives discussed +below. This is very similar to the (now removed) BackendPolicy resource in the API, +but also borrows some concepts from the [ServicePolicy +proposal](https://github.com/kubernetes-sigs/gateway-api/issues/611). + +### Policy Attachment for Ingress +When talking about Direct Attached Policy attaching to Gateway resources for +ingress use cases (as discussed in GEP-2648), the flow is relatively +straightforward. A policy can reference the resource it wants to apply to, and +only affects that resource. + + +![Simple Ingress Example](images/2649-ingress-simple.png) + +However, an Inherited Policy can attach to a parent resource, and then each policy +applies to the referenced resource and everything below it in terms of hierarchy. + +In the simple example above, the TimeoutPolicy _attaches_ to the Gateway but +_affects_ the HTTPRoute. That's the very thing that makes this an Inherited +Policy. + +Although the next example is likely more complex than many real world +use cases, it helps demonstrate how policy attachment can work across +namespaces. + +![Complex Ingress Example](images/2649-ingress-complex.png) + +In this example, the Gateway has a TimeoutPolicy attached, which affects the +HTTPRoute in the App namespace. That HTTPRoute also has the Direct Attached +RetryPolicy attached, which affects the HTTPRoute itself, and one of the backends +has a HealthCheckPolicy attached to the Service, which is also a Direct Attached +Policy. + +This shows how Direct and Inherited Policies can be attached to varied objects +and still apply the relevant configuration. + +As a preview of a later section though, ask yourself: If I was the owner of the +HTTPRoute, how would I know what Policy was affecting it at any point in time? + +### Policy Attachment for Mesh +Although there is a great deal of overlap between ingress and mesh use cases, +mesh enables more complex policy attachment scenarios. For example, you may want +to apply policy to requests from a specific namespace to a backend in another +namespace. + +![Simple Mesh Example](images/2649-mesh-simple.png) + +Policy attachment can be quite simple with mesh. Policy can be applied to any +resource in any namespace but it can only apply to requests from the same +namespace if the target is in a different namespace. + +At the other extreme, policy can be used to apply to requests from a specific +workload to a backend in another namespace. A route can be used to intercept +these requests and split them between different backends (foo-a and foo-b in +this case). + +![Complex Mesh Example](images/2649-mesh-complex.png) + +### Policy TargetRef API + +Each Policy resource MUST include a single `targetRef` field. It must not +target more than one resource at a time, but it can be used to target larger +resources such as Gateways or Namespaces that may apply to multiple child +resources. + +As with most APIs, there are countless ways we could choose to expand this in +the future. This includes supporting multiple targetRefs and/or label selectors. +Although this would enable compelling functionality, it would increase the +complexity of an already complex API and potentially result in more conflicts +between policies. Although we may choose to expand the targeting capabilities +in the future, at this point it is strongly preferred to start with a simpler +pattern that still leaves room for future expansion. + +The `targetRef` field MUST have the following structure: + +```go +// PolicyTargetReference identifies an API object to apply policy to. +type PolicyTargetReference struct { + // Group is the group of the target resource. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Group string `json:"group"` + + // Kind is kind of the target resource. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Kind string `json:"kind"` + + // Name is the name of the target resource. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Name string `json:"name"` + + // Namespace is the namespace of the referent. When unspecified, the local + // namespace is inferred. Even when policy targets a resource in a different + // namespace, it may only apply to traffic originating from the same + // namespace as the policy. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +optional + Namespace string `json:"namespace,omitempty"` +} +``` + +### Sample Policy API +The following structure can be used as a starting point for any Policy resource +using this API pattern. Note that the PolicyTargetReference struct defined above +will be distributed as part of the Gateway API. + +```go +// ACMEServicePolicy provides a way to apply Service policy configuration with +// the ACME implementation of the Gateway API. +type ACMEServicePolicy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of ACMEServicePolicy. + Spec ACMEServicePolicySpec `json:"spec"` + + // Status defines the current state of ACMEServicePolicy. + Status ACMEServicePolicyStatus `json:"status,omitempty"` +} + +// ACMEServicePolicySpec defines the desired state of ACMEServicePolicy. +type ACMEServicePolicySpec struct { + // TargetRef identifies an API object to apply policy to. + TargetRef gatewayv1a2.PolicyTargetReference `json:"targetRef"` + + // Override defines policy configuration that should override policy + // configuration attached below the targeted resource in the hierarchy. + // +optional + Override *ACMEPolicyConfig `json:"override,omitempty"` + + // Default defines default policy configuration for the targeted resource. + // +optional + Default *ACMEPolicyConfig `json:"default,omitempty"` +} + +// ACMEPolicyConfig contains ACME policy configuration. +type ACMEPolicyConfig struct { + // Add configurable policy here +} + +// ACMEServicePolicyStatus defines the observed state of ACMEServicePolicy. +type ACMEServicePolicyStatus struct { + // Conditions describe the current conditions of the ACMEServicePolicy. + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} +``` + +### Hierarchy +Each policy MAY include default or override values. Default values are given +precedence from the bottom up, while override values are top down. That means +that a default attached to a Backend will have the highest precedence among +default values while an override value attached to a GatewayClass will have the +highest precedence overall. + +![Ingress and Sidecar Hierarchy](images/2649-hierarchy.png) + +To illustrate this, consider 3 resources with the following hierarchy: +A > B > C. When attaching the concept of defaults and overrides to that, the +hierarchy would be expanded to this: + +A override > B override > C override > C default > B default > A default. + +Note that the hierarchy is reversed for defaults. The rationale here is that +overrides usually need to be enforced top down while defaults should apply to +the lowest resource first. For example, if an admin needs to attach required +policy, they can attach it as an override to a Gateway. That would have +precedence over Routes and Services below it. On the other hand, an app owner +may want to set a default timeout for their Service. That would have precedence +over defaults attached at higher levels such as Route or Gateway. + +If using defaults _and_ overrides, each policy resource MUST include 2 structs +within the spec. One with override values and the other with default values. + +In the following example, the policy attached to the Gateway requires cdn to +be enabled and provides some default configuration for that. The policy attached +to the Route changes the value for one of those fields (includeQueryString). + +```yaml +kind: CDNCachingPolicy # Example of implementation specific policy name +spec: + override: + cdn: + enabled: true + default: + cdn: + cachePolicy: + includeHost: true + includeProtocol: true + includeQueryString: true + targetRef: + kind: Gateway + name: example +--- +kind: CDNCachingPolicy +spec: + default: + cdn: + cachePolicy: + includeQueryString: false + targetRef: + kind: HTTPRoute + name: example +``` + +In this final example, we can see how the override attached to the Gateway has +precedence over the default drainTimeout value attached to the Route. At the +same time, we can see that the default connectionTimeout attached to the Route +has precedence over the default attached to the Gateway. + +Also note how the different resources interact - fields that are not common across +objects _may_ both end up affecting the final object. + +![Inherited Policy Example](images/2649-policy-hierarchy.png) + +#### Supported Resources +It is important to note that not every implementation will be able to support +policy attachment to each resource described in the hierarchy above. When that +is the case, implementations MUST clearly document which resources a policy may +be attached to. + +## Examples + +This section provides some examples of various types of Policy objects, and how +merging, `defaults`, `overrides`, and other interactions work. + +### Inherited Policy Attachment + +It also could be useful to be able to _default_ the `minimumTLSVersion` setting +across multiple Gateways. + +This version of the above Policy allows this: +```yaml +apiVersion: networking.example.io/v1alpha1 +kind: TLSMinimumVersionPolicy +metadata: + name: minimum12 + namespace: appns +spec: + defaults: + minimumTLSVersion: 1.2 + targetRef: + name: appns + group: "" + kind: namespace +``` + +This Inherited Policy is using the implicit hierarchy that all resources belong +to a namespace, so attaching a Policy to a namespace means affecting all possible +resources in a namespace. Multiple hierarchies are possible, even within Gateway +API, for example Gateway -> Route, Gateway -> Route -> Backend, Gateway -> Route +-> Service. GAMMA Policies could conceivably use a hierarchy of Service -> Route +as well. + +Note that this will not be very discoverable for Gateway owners in the absence of +a solution to the Policy status problem. This is being worked on and this GEP will +be updated once we have a design. + +Conceivably, a security or admin team may want to _force_ Gateways to have at least +a minimum TLS version of `1.2` - that would be a job for `overrides`, like so: + +```yaml +apiVersion: networking.example.io/v1alpha1 +kind: TLSMinimumVersionPolicy +metadata: + name: minimum12 + namespace: appns +spec: + overrides: + minimumTLSVersion: 1.2 + targetRef: + name: appns + group: "" + kind: namespace +``` + +This will make it so that _all Gateways_ in the `default` namespace _must_ use +a minimum TLS version of `1.2`, and this _cannot_ be changed by Gateway owners. +Only the Policy owner can change this Policy. + +### Handling non-scalar values + +In this example, we will assume that at some future point, HTTPRoute has grown +fields to configure retries, including a field called `retryOn` that reflects +the HTTP status codes that should be retried. The _value_ of this field is a +list of strings, being the HTTP codes that must be retried. The `retryOn` field +has no defaults in the field definitions (which is probably a bad design, but we +need to show this interaction somehow!) + +We also assume that a Inherited `RetryOnPolicy` exists that allows both +defaulting and overriding of the `retryOn` field. + +A full `RetryOnPolicy` to default the field to the codes `501`, `502`, and `503` +would look like this: +```yaml +apiVersion: networking.example.io/v1alpha1 +kind: RetryOnPolicy +metadata: + name: retryon5xx + namespace: appns +spec: + defaults: + retryOn: + - "501" + - "502" + - "503" + targetRef: + kind: Gateway + group: gateway.networking.k8s.io + name: we-love-retries +``` + +This means that, for HTTPRoutes that do _NOT_ explicitly set this field to something +else, (in other words, they contain an empty list), then the field will be set to +a list containing `501`, `502`, and `503`. (Notably, because of Go zero values, this +would also occur if the user explicitly set the value to the empty list.) + +However, if a HTTPRoute owner sets any value other than the empty list, then that +value will remain, and the Policy will have _no effect_. These values are _not_ +merged. + +If the Policy used `overrides` instead: +```yaml +apiVersion: networking.example.io/v1alpha1 +kind: RetryOnPolicy +metadata: + name: retryon5xx + namespace: appns +spec: + overrides: + retryOn: + - "501" + - "502" + - "503" + targetRef: + kind: Gateway + group: gateway.networking.k8s.io + name: you-must-retry +``` + +Then no matter what the value is in the HTTPRoute, it will be set to `501`, `502`, +`503` by the Policy override. + +### Interactions between defaults, overrides, and field values + +All HTTPRoutes that attach to the `YouMustRetry` Gateway will have any value +_overwritten_ by this policy. The empty list, or any number of values, will all +be replaced with `501`, `502`, and `503`. + +Now, let's also assume that we use the Namespace -> Gateway hierarchy on top of +the Gateway -> HTTPRoute hierarchy, and allow attaching a `RetryOnPolicy` to a +_namespace_. The expectation here is that this will affect all Gateways in a namespace +and all HTTPRoutes that attach to those Gateways. (Note that the HTTPRoutes +themselves may not necessarily be in the same namespace though.) + +If we apply the default policy from earlier to the namespace: +```yaml +apiVersion: networking.example.io/v1alpha1 +kind: RetryOnPolicy +metadata: + name: retryon5xx + namespace: appns +spec: + defaults: + retryOn: + - "501" + - "502" + - "503" + targetRef: + kind: Namespace + group: "" + name: appns +``` + +Then this will have the same effect as applying that Policy to every Gateway in +the `default` namespace - namely that every HTTPRoute that attaches to every +Gateway will have its `retryOn` field set to `501`, `502`, `503`, _if_ there is no +other setting in the HTTPRoute itself. + +With two layers in the hierarchy, we have a more complicated set of interactions +possible. + +Let's look at some tables for a particular HTTPRoute, assuming that it does _not_ +configure the `retryOn` field, for various types of Policy at different levels. + +#### Overrides interacting with defaults for RetryOnPolicy, empty list in HTTPRoute + +||None|Namespace override|Gateway override|HTTPRoute override| +|----|-----|-----|----|----| +|No default|Empty list|Namespace override| Gateway override Policy| HTTPRoute override| +|Namespace default| Namespace default| Namespace override | Gateway override | HTTPRoute override | +|Gateway default| Gateway default | Namespace override | Gateway override | HTTPRoute override | +|HTTPRoute default| HTTPRoute default | Namespace override | Gateway override | HTTPRoute override| + +#### Overrides interacting with other overrides for RetryOnPolicy, empty list in HTTPRoute +||No override|Namespace override A|Gateway override A|HTTPRoute override A| +|----|-----|-----|----|----| +|No override|Empty list|Namespace override| Gateway override| HTTPRoute override| +|Namespace override B| Namespace override B| Namespace override
first created wins
otherwise first alphabetically | Namespace override B | Namespace override B| +|Gateway override B| Gateway override B | Namespace override A| Gateway override
first created wins
otherwise first alphabetically | Gateway override B| +|HTTPRoute override B| HTTPRoute override B | Namespace override A| Gateway override A| HTTPRoute override
first created wins
otherwise first alphabetically| + +#### Defaults interacting with other defaults for RetryOnPolicy, empty list in HTTPRoute +||No default|Namespace default A|Gateway default A|HTTPRoute default A| +|----|-----|-----|----|----| +|No default|Empty list|Namespace default| Gateway default| HTTPRoute default A| +|Namespace default B| Namespace default B| Namespace default
first created wins
otherwise first alphabetically | Gateway default A | HTTPRoute default A| +|Gateway default B| Gateway default B| Gateway default B| Gateway default
first created wins
otherwise first alphabetically | HTTPRoute default A| +|HTTPRoute default B| HTTPRoute default B| HTTPRoute default B| HTTPRoute default B| HTTPRoute default
first created wins
otherwise first alphabetically| + + +Now, if the HTTPRoute _does_ specify a RetryPolicy, +it's a bit easier, because we can basically disregard all defaults: + +#### Overrides interacting with defaults for RetryOnPolicy, value in HTTPRoute + +||None|Namespace override|Gateway override|HTTPRoute override| +|----|-----|-----|----|----| +|No default| Value in HTTPRoute|Namespace override| Gateway override | HTTPRoute override| +|Namespace default| Value in HTTPRoute| Namespace override | Gateway override | HTTPRoute override | +|Gateway default| Value in HTTPRoute | Namespace override | Gateway override | HTTPRoute override | +|HTTPRoute default| Value in HTTPRoute | Namespace override | Gateway override | HTTPRoute override| + +#### Overrides interacting with other overrides for RetryOnPolicy, value in HTTPRoute +||No override|Namespace override A|Gateway override A|HTTPRoute override A| +|----|-----|-----|----|----| +|No override|Value in HTTPRoute|Namespace override A| Gateway override A| HTTPRoute override A| +|Namespace override B| Namespace override B| Namespace override
first created wins
otherwise first alphabetically | Namespace override B| Namespace override B| +|Gateway override B| Gateway override B| Namespace override A| Gateway override
first created wins
otherwise first alphabetically | Gateway override B| +|HTTPRoute override B| HTTPRoute override B | Namespace override A| Gateway override A| HTTPRoute override
first created wins
otherwise first alphabetically| + +#### Defaults interacting with other defaults for RetryOnPolicy, value in HTTPRoute +||No default|Namespace default A|Gateway default A|HTTPRoute default A| +|----|-----|-----|----|----| +|No default|Value in HTTPRoute|Value in HTTPRoute|Value in HTTPRoute|Value in HTTPRoute| +|Namespace default B|Value in HTTPRoute|Value in HTTPRoute|Value in HTTPRoute|Value in HTTPRoute| +|Gateway default B|Value in HTTPRoute|Value in HTTPRoute|Value in HTTPRoute|Value in HTTPRoute| +|HTTPRoute default B|Value in HTTPRoute|Value in HTTPRoute|Value in HTTPRoute|Value in HTTPRoute| + + +## User discoverability and status + +### Standard label on CRD objects + +Each CRD that defines an Inherited Policy object MUST include a label that specifies +that it is a Policy object, and that label MUST specify that the object is an +`inherited` one. + +The label is `gateway.networking.k8s.io/policy: inherited`. + +This solution is intended to allow both users and tooling to identify which CRDs +in the cluster should be treated as Policy objects, and so is intended to help +with discoverability generally. It will also be used by the forthcoming `kubectl` +plugin. + +### Conditions + +Implementations using Policy objects MUST include a `spec` and `status` stanza, +and the `status` stanza MUST contain a `conditions` stanza, using the standard +Condition format. + +Policy authors should consider namespacing the `conditions` stanza with a +`controllerName`, as in Route status, if more than one implementation will be +reconciling the Policy type. + +#### On `Policy` objects + +Each Inherited Policy MUST populate the `Accepted` condition and reasons +as defined in the Go spec, a snapshot of which is included below. The canonical +representation is in the actual Go files. (At the time of writing, this is in +`apis/v1alpha2/policy_types.go`) + +This allows the responsible controller to indicate that the Policy has been +accepted for processing. + +```go +// PolicyConditionType is a type of condition for a policy. +type PolicyConditionType string + +// PolicyConditionReason is a reason for a policy condition. +type PolicyConditionReason string + +const ( + // PolicyConditionAccepted indicates whether the policy has been accepted or rejected + // by a targeted resource, and why. + // + // Possible reasons for this condition to be True are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "Conflicted" + // * "Invalid" + // * "TargetNotFound" + // + PolicyConditionAccepted PolicyConditionType = "Accepted" + + // PolicyReasonAccepted is used with the "Accepted" condition when the policy has been + // accepted by the targeted resource. + PolicyReasonAccepted PolicyConditionReason = "Accepted" + + // PolicyReasonConflicted is used with the "Accepted" condition when the policy has not + // been accepted by a targeted resource because there is another policy that targets the same + // resource and a merge is not possible. + PolicyReasonConflicted PolicyConditionReason = "Conflicted" + + // PolicyReasonInvalid is used with the "Accepted" condition when the policy is syntactically + // or semantically invalid. + PolicyReasonInvalid PolicyConditionReason = "Invalid" + + // PolicyReasonTargetNotFound is used with the "Accepted" condition when the policy is attached to + // an invalid target resource + PolicyReasonTargetNotFound PolicyConditionReason = "TargetNotFound" +) +``` +#### On targeted resources + +Implementations that use Inherited Policy objects SHOULD put a Condition into +`status.Conditions` of any objects affected by a Inherited Policy, if that field +is present. + +If they do, that Condition MUST have a `type` ending in `PolicyAffected` (like +`gateway.networking.k8s.io/PolicyAffected`), +and have the optional `observedGeneration` field kept up to date when the `spec` +of the Policy-attached object changes. + +Implementations SHOULD use their own unique domain prefix for this Condition +`type` - it is recommended that implementations use the same domain as in the +`controllerName` field on GatewayClass (or some other implementation-unique +domain for implementations that do not use GatewayClass). + +For objects that do _not_ have a `status.Conditions` field available (`Secret` +is a good example), that object SHOULD instead have a label of +`gateway.networking.k8s.io/PolicyAffected: true` (or with an +implementation-specific domain prefix) added instead. + +Because these Conditions or labels are namespaced per-implementation, +implementations SHOULD: + +- Add the Condition or label if an object is policy affected when it is not + already present +- Remove the Condition or label when the last policy object stops referencing + the targeted object. + +The intent here is to give _some_ feedback that the object is affected by a Policy, +even if the details are difficult to communicate. + +#### Further status design + +Further status design for Inherited Policy is required, but needs to solve the +complexity and fanout problems listed above. Further design is therefore currently +up for discussion. + +Community members are encouraged to submit updates to this GEP with further patterns. diff --git a/site-src/ko/geps/gep-2649/metadata.yaml b/site-src/ko/geps/gep-2649/metadata.yaml new file mode 100644 index 0000000000..403a0c72ec --- /dev/null +++ b/site-src/ko/geps/gep-2649/metadata.yaml @@ -0,0 +1,21 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 2649 +name: Inherited Policy Attachment +status: Provisional +authors: + - youngnick + - robscott +relationships: + extends: + - name: Metaresources and Policy Attachment + number: 713 + description: Split out Inherited Policy Attachment +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: + - "https://github.com/kubernetes-sigs/gateway-api/discussions/2927" +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: + - "https://github.com/kubernetes-sigs/gateway-api/pull/2813" diff --git a/site-src/ko/geps/gep-2659/index.md b/site-src/ko/geps/gep-2659/index.md new file mode 100644 index 0000000000..00cabd8e2a --- /dev/null +++ b/site-src/ko/geps/gep-2659/index.md @@ -0,0 +1,165 @@ +# GEP-2659: Document and improve the GEP process + +* Issue: [#2659](https://github.com/kubernetes-sigs/gateway-api/issues/2659) +* Type: Memorandum +* Status: Accepted + +(See [status definitions](../overview.md#gep-states).) + +## TLDR + +This GEP clarifies some details about GEPs, and adds relationships and a new +status. + + +## Goals + +- Enumerate how we should use RFC2119 language +- Add relationships between GEPs +- Add a metadata YAML schema for GEPs, including the new relationships +- Add a new status to cover some only recently noticed cases +- Update existing documentation outside this GEP to support the new material + +## Introduction + +As part of preparing for work to split up GEP-713, we (the Gateway API and GAMMA +maintainers) have noticed a few shortcomings in our GEP process. + +In particular, we have some GEPs that are very different to other GEPs. +[GEP-1324](../gep-1324/index.md) is a good example, +as it lays out the general agreement and use cases for the GAMMA initiative, but +has no firm deliverables of its own. In fact, its main purpose was to ensure +that the community was in agreement on the language around and scope of the +problem of representing Mesh config using Gateway API primitives. Essentially, +it lays out a shared understanding of the problem space, as a basis for further +work (in the form of subsequent GEPs). However, our current GEP system of checklists +for graduating levels fits this type of GEP poorly. + +Additionally, we've had two GEPs moved to Declined ([GEP-735: TCP and UDP address +matching](../gep-735/index.md) and +[GEP-1282: Describing Backend Properties](../gep-1282/index.md)). +In the case of GEP-1282, we now have a replacement GEP, +[GEP-1897: BackendTLSPolicy](../gep-1897/index.md) +which obsoletes the older GEP. But we have no way of representing this +relationship (or any other, in fact) between GEPs at the moment. + +With these previous two changes, the addition of a metadata YAML file, similar +to what the KEP process uses, seems like it is increasingly necessary. This GEP +introduces a schema, which will be detailed in `.go` files rather than completely +in this document. + +Lastly, we should clarify our use of [RFC2119](https://www.rfc-editor.org/rfc/rfc2119.txt) +language - we use MUST, SHOULD, MAY and so on as per that RFC in general, +but there is an extension in [RFC8174](https://www.rfc-editor.org/rfc/rfc8174.txt) +that adds that these words are only to be interpreted per the RFC when they are +in ALL CAPS, and "must" "should", "may" are to be interpreted in their usual +English meaning (which is not as strong as the RFC2119 one). This seems like +a _very_ good idea to adopt to me. + +## Proposals + +### Adopt the RFC8174 modification to RFC2119 language + +RFC8174 clarifies that the reserved words MUST be in all-caps to have their +assigned meaning. This should make the spec clearer over time as we migrate. + +### Addition of a new GEP status + +We will introduce a new GEP status, `Memorandum`, that marks a GEP as recording +an agreement on either the definition of a problem, its scope +and a common language, or further process changes to the GEP process itself. + +The defining characteristic here is that the GEP MUST NOT result in any changes +to the Gateway API spec, and MAY result in further GEPs to further clarify. +For GEPs that _do_ make changes to the API, but also require further GEPs to +clarify, they SHOULD use the new "Extended By" relationship instead. + +Memorandum GEPs should be used sparingly, and should form the umbrella for a +significant amount of work, particularly work that may have parts that can +move through the GEP phases at different speeds. + +The status is reached when a Memorandum GEP is merged, although as we will document +in the "Addition of GEP relationships" section, it can still be Extended +or Obsoleted. + +Existing GEPs that meet this criteria will be gradually moved to be proper +Memorandum GEPs after this GEP is merged. + +### Addition of YAML metadata file + +The core Gateway API maintainers were hoping not to need metadata YAMLs for a +while, but the addition of relationships has turbocharged the need for machine +parseable GEP metadata. + +This should also help with building display for GEPs; theoretically we can build +tooling that will let people slice the list of GEPs by whatever dimensions +we (or they) wish. + +Similarly to the `ConformanceReport` object, I'm proposing to make CRD definitions +for this `GEPDetails` object, which will not be included in the usual CRD +definitions for Gateway API, nor will it be part of the regular API spec. + +The use of a CRD is just to make the schema more similar to the other schemas +in this repository. + +With that said, here's a rough sample of what a GEPMetadata object will look like: + +```yaml +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 2659 +name: Document and improve the GEP process +status: Memorandum +authors: + - youngnick +relationships: + # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely + # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field + # set back to this GEP, and MUST be moved to Declined. + obsoletes: {} + obsoletedBy: {} + # extends indicates that a GEP extends the linked GEP, adding more detail + # or additional implementation. The extended GEP MUST have its extendedBy + # field set back to this GEP. + extends: {} + extendedBy: {} + # seeAlso indicates other GEPs that are relevant in some way without being + # covered by an existing relationship. + seeAlso: {} +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: {} +# featureNames is a list of the feature names introduced by the GEP, if there +# are any. This will allow us to track which feature was introduced by which GEP. +featureNames: {} +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: + - "https://github.com/kubernetes-sigs/gateway-api/pull/2689" +``` + +### Addition of GEP relationships + +As you can see in the previous section, this GEP adds three relationships between +GEPs: +- `Obsoletes` and its backreference `ObsoletedBy` - when a GEP is made obsolete + by another GEP, and has its functionality completely replaced. +- `Extends` and its backreference `ExtendedBy` - when a GEP has additional details + or implementation added in another GEP. +- `SeeAlso` - when a GEP is relevant to another GEP, but is not affected in any + other defined way. + +Each stanza in `relationships` includes a `number`, `name`, and a optional free-form +`description` field, which can be used to better describe the relationship. + +At this time it's the updater's responsibility to ensure that both directions +are created for bidirectional relationships. + +Further relationships may be added at a later date (at which time that GEP will +have an `Extends` relationship to this one). + +Because of the addition of structured definitions for these relationships, the +relationships will _not_ be recorded in the main GEP file (it's anticipated +that the metadata will eventually be rendered in table form in the canonical +display on the website for general consumption, and PRs will need to create or +update a YAML file for each GEP change). diff --git a/site-src/ko/geps/gep-2659/metadata.yaml b/site-src/ko/geps/gep-2659/metadata.yaml new file mode 100644 index 0000000000..e98ec3f7a2 --- /dev/null +++ b/site-src/ko/geps/gep-2659/metadata.yaml @@ -0,0 +1,21 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 2659 +name: Document and improve the GEP process +type: Memorandum +status: Accepted +relationships: + seeAlso: + - number: 917 + name: Gateway API Conformance Testing + description: GEP is Memorandum type + - number: 922 + name: Gateway API Versioning + description: GEP is Memorandum type + - number: 1324 + name: Service Mesh in Gateway API + description: GEP is Memorandum type +authors: + - youngnick +changelog: + - "https://github.com/kubernetes-sigs/gateway-api/pull/2689" diff --git a/site-src/ko/geps/gep-2722/index.md b/site-src/ko/geps/gep-2722/index.md new file mode 100644 index 0000000000..135e2c7670 --- /dev/null +++ b/site-src/ko/geps/gep-2722/index.md @@ -0,0 +1,642 @@ +# GEP-2722: Goals and UX for gwctl + +* Issue: [#2722](https://github.com/kubernetes-sigs/gateway-api/issues/2722) +* Status: Memorandum + +## TLDR + +TLDR: This GEP proposes `gwctl`, a new command line tool designed to streamline + the experience of working with Gateway API resources. It offers a familiar + kubectl-like interface for viewing resources while providing more detailed and + informative output that is specifically focused on the Gateway API. For + advanced filtering and other in-depth features, `gwctl` can be effectively + used alongside `kubectl`. + +## Motivations + +* Limited kubectl customizability for CRDs: + * kubectl's customization capabilities for CRDs (through + `additionalPrinterColumns`) is constrained, limiting the ability to create + optimal views for Gateway API resources. +* Complex policy attachment management: + * As described in [GEP-713](../gep-713/index.md), + policies present a valuable mechanism for expanding the capabilities of + Gateway API resources. However, discoverability poses a challenge due to + the absence of a clear connection between resources and their associated + policies. There have been growing questions around suitability of policies + as a means to provide extensions. +* Challenging multi-resource model navigation: + * Comprehending the relationships between multiple Gateway API resources can + be challenging within kubectl. + +## Goals + +* Greater control over output formatting and presentation: + * Offer greater control over output formatting and presentation, enhancing + visibility and understanding of Gateway API resources. +* Improved policy discoverability, increasing adoption and usability: + * Make policies easily discoverable, aiding in the adoption and fostering + broader acceptance of policies as an extension mechanism. +* Simplified multi-resource model navigation: + * Facilitate navigation of the multi-resource model by making connections + between Gateway API resources explicit, aiding in configuration, + troubleshooting, and issue identification. +* Proactive error detection and reporting: + * Leverage native understanding of resource relationships to proactively + detect and report on potential configuration errors, further simplifying + issue identification and resolution. This would complement the ability of + users to readily pinpoint configuration problems themselves. +* Provide incentive for policy implementations that are consistent across cloud + providers: + * Encourage the adoption of consistent policy implementations across + different Gateway API providers, promoting interoperability and + predictability. + +## Commands Specification + +### Milestone 1 + +#### Supported Commands: + +* **get**: Retrieves information about specified resources without including + additional information from related resources. +* **describe**: Provides detailed information about specified resources, + including augmented information from related resources. + +#### Supported Resources: + +* gatewayclass +* gateways +* httproutes +* namespaces +* backends (not a native k8s resource) +* policycrds (not a native k8s resource) +* policies (not a native k8s resource) + +#### Filtering Options: + +* `-n` **Namespace**: Filters resources by namespace. Applicable to all + resources except cluster-scoped resources. +* `-l` **Labels**: Filters resources by labels. Applicable to all resources. +* `-A` **All Namespaces**: Fetches resources across all namespaces (redundant + for cluster-scoped resources). +* `-t` **Target Resource**: Filters policies based on the target resource type + they apply to. Applicable only to the policies resource. + * Syntax: `-t =,=,...` + * Supported keys: + * kind: Resource kind (e.g., "httproute", "gateway") + * namespace: Resource namespace + * name: Resource name + * group: Resource API group + +#### Output Formats: + +* **describe**: Fixed format, not customizable. Shows comprehensive resource + information with details from related resources. + +* **get**: + * One-line format (default): Displays basic resource information in a single + line. + * YAML format (-o yaml): Presents resource information in the YAML data + format. + * JSON format (-o json): Presents resource information in the JSON data + format. + * Wide format (-o wide): Includes additional columns beyond those displayed in + the one-line format. + +
+ Output columns while using get + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ResourceOutput ColumnsDescriptionVisibility (Defaults to always unless specified otherwise)
gatewayclassNAMEName of the GatewayClass
CONTROLLERController managing the GatewayClass
ACCEPTEDWhether the GatewayClass is accepted by the controller
AGEAge of the GatewayClass
GATEWAYSCount of Gateways using this GatewayClass-o wide
DESCRIPTIONDescription from the GatewayClass-o wide
gatewayNAMEName of the Gateway
CLASSClass of the Gateway
ADDRESSESAddresses of the Gateway (displayed using + n more) +
PORTSPorts exposed by the Gateway
PROGRAMMEDWhether the Gateway is programmed
AGEAge of the Gateway
POLICIESCount of policies affecting this Gateway-o wide
HTTPROUTESCount of HTTPRoutes that are attached to this Gateway-o wide
httprouteNAMESPACENamespace of the HTTPRoute
NAMEName of the HTTPRoute
HOSTNAMESHostnames associated with the HTTPRoute
PARENT REFSCount of parent references of the HTTPRoute (e.g., Gateways)
AGEAge of the HTTPRoute
POLICIESCount of policies affecting this HTTPRoute-o wide
namespaceNAMEName of the namespace
STATUSStatus of the namespace
AGEAge of the namespace
POLICIESCount of policies affecting this Namespace-o wide
backendNAMEName of the backend
TYPEType of the backend (currently only supports Services)
REFERRED BY ROUTESHTTPRoutes that refer to the backend (displayed using + n more) +
AGEAge of the backend
POLICIESCount of policies affecting this Backend-o wide
policycrdNAMEName of the Policy CRD in the form <kind.group>
POLICY TYPEType of policy defined by the CRD (Inherited or Direct)
SCOPEScope of the policy (Namespaced or Cluster)
POLICIES COUNTCount of policy resources of this particular type.-o wide
AGEAge of the Policy CRD
policyNAMEName of the policy
KINDThe kind of policy in the form <kind.group> +
TARGET NAMEName of the resource the policy applies to
TARGET KINDThe kind of target resource in the form
POLICY TYPEType of policy (Inherited or Direct)
AGEAge of the Policy CRD
+
+ +#### Additional Notes: + +* The behavior of `get` and `describe` commands is similar to kubectl, with + `get` focusing on concise resource information and `describe` providing + comprehensive details. +* `backends` represent resources that can be attached as backends to HTTPRoutes + (currently limited to k8s services). +* `policycrds` and `policies` are not native k8s resources but represent subsets + of CRDs and custom resource objects related to policies. (`policycrds` are + identified by + [PolicyLabelKey](https://github.com/kubernetes-sigs/gateway-api/blob/5658635bce70f3a52b6936ad5a99249a4f5116ad/apis/v1alpha2/policy_types.go#L31C2-L31C16)) + +#### Examples of commands that should be supported: + +* `gwctl get gateways -n foo` (Lists basic information about Gateways in the + "foo" namespace) +* `gwctl get httproutes -l version=v1,app=myapp` (Lists basic information about + HTTPRoutes with the labels "version=v1" and "app=myapp") +* `gwctl get gateways -n foo -o yaml` (Shows detailed Gateway information in + YAML format within the "foo" namespace) +* `gwctl get httproutes -l version=v1,app=myapp -o json` (Shows detailed + HTTPRoute information in JSON format with specified labels) +* `gwctl describe gateways my-gateway` (Provides comprehensive details about the + "my-gateway" Gateway, including information from related resources) +* `gwctl describe policies my-policy` (Shows detailed information about the + "my-policy" policy, encompassing data from relevant any related resources when + applicable) +* `gwctl get policies -t kind=httproute` (Lists basic information about policies that apply to HTTPRoutes) + +#### Distribution +To ensure gwctl is widely accessible and easy to adopt, the following +distribution mechanisms will be provided: + +* **Prebuilt Binaries:** Prebuilt binaries for various platforms (Linux, macOS, + Windows) will be made available for download. Tooling like + [GoReleaser](https://goreleaser.com/) can be used to streamline some of the + build processes. Binaries will be offered in two variants: + * `gwctl` for standalone use. + * `kubectl-gw` for use as a kubectl plugin (`kubectl gw`). +* **Kubectl Plugin Integration:** gwctl will be integrated with + [Krew](https://github.com/kubernetes-sigs/krew), the kubectl plugin manager. + This should immensely help with improving discoverability of the plugin, + allowing easier installation, and handling automatic updates for the user. +* **Versioning:** gwctl versions will be aligned with Gateway API releases (for + the time when gwctl is developed within the same repository as Gateway API) + * As gwctl matures, the need for maintaining it within the primary Gateway API + repository will be reassessed. Factors such as a potential divergence in + release cadence, independent contributor growth or the desire to reduce the + triage workload for Gateway API maintainers could motivate a move to a + separate repository. + +### Future Milestones +* Each output of `describe` will include an extra `Analysis` field. This field + will display any errors or other analysis information associated with the + resource. +* Investigate the feasibility and any advantages of using Graphviz or webview + for visualizing data and presenting information in a visually appealing + manner. +* Evaluate how gwctl can be extended to support [Mesh use + cases](/concepts/gamma/#how-the-gateway-api-works-for-service-mesh) + +## References + +* [GEP-713: Metaresources and Policy + Attachment](../gep-713/index.md) + +## Sample outputs + +The example outputs provided below serve as a guideline for the implementation, +outlining the range of values that may be presented: + +* `gwctl get gatewayclass -o wide` + ``` + NAME CONTROLLER ACCEPTED AGE DESCRIPTION Gateways + bar-com-internal-gateway-class bar.baz/internal-gateway-class True 100d Internal Load Balancer 10 + foo-com-external-gateway-class foo.com/external-gateway-class True 365d External Load Balancer 25 + ``` + +* `gwctl get gateway -o wide` + ``` + NAME CLASS ADDRESSES PORTS PROGRAMMED AGE POLICIES HTTPROUTES + demo-gateway-2 external-class 10.0.0.1 80 True 20d 10 5 + abc-gateway-12345 internal-class 192.168.100.5 443,8080 False 5d 2 1 + random-gateway regional-internal-class 10.11.12.13 8443 Unknown 3s 3 5 + ``` + +* `gwctl get httproute -o wide` + ``` + NAMESPACE NAME HOSTNAMES PARENT REFS AGE POLICIES + default foo-httproute-1 example.com,example2.com + 1 more ns2/demo-gateway-2 5m 2 + default qmn-httproute-100 example.com demo-gateway-1 5m 1 + ns1 bar-route-21 foo.com,bar.com + 5 more default/demo-gateway-200 5m 3 + ns2 bax-httproute-18777 None ns1/demo-gateway-345 5m 4 + ``` + +* `gwctl get namespace -o wide` + ``` + NAME STATUS AGE POLICIES + default Active 46d 3 + kube-system Active 46d 5 + ``` + +* `gwctl get backend -o wide` + ``` + NAME TYPE REFERRED BY ROUTES AGE POLICIES + foo-svc Service foo-httproute-1,abc-httproute-33 + 4 more 45m 5 + bar-baz-svc Service bar-httproute 11d 1 + ``` + +* `gwctl get policycrds -o wide` + ``` + NAME POLICY TYPE SCOPE POLICIES COUNT AGE + healthcheckpolicies.foo.com Direct Namespaced 1 5d + retryonpolicies.foo.com Direct Namespaced 2 4d + timeoutpolicies.bar.com Inherited Cluster 1 10m + tlsminimumversionpolicies.baz.com Direct Namespaced 3 45s + ``` + +* `gwctl get policies -o wide` + ``` + NAME KIND TARGET NAME TARGET KIND POLICY TYPE AGE + demo-timeout-policy-on-gatewayclass TimeoutPolicy.foo.com foo-com-external-gateway-class GatewayClass Inherited 10d + demo-timeout-policy-on-namespace TimeoutPolicy.foo.com default Namespace Inherited 10d + demo-health-check-1 HealthCheckPolicy.bar.com demo-gateway-1 Gateway Direct 10d + demo-retry-policy-1 RetryOnPolicy.baz.com demo-gateway-1 Gateway Direct 10d + demo-retry-policy-2 RetryOnPolicy.baz.com demo-httproute-2 HTTPRoute Direct 10d + demo-tls-min-version-policy-1 TLSMinimumVersionPolicy.foobar.com demo-gateway-3 Gateway Direct 10d + demo-tls-min-version-policy-2 TLSMinimumVersionPolicy.foobar.com demo-gateway-4 Gateway Direct 10d + ``` + +* `gwctl describe gateway demo-gateway` + ``` + Name: demo-gateway + Namespace: default + Labels: + Annotations: + annotation.foo: value1 + annotation.bar.baz: abcdefghijkl + API Version: gateway.networking.k8s.io/v1beta1 + Kind: Gateway + Metadata: + creationTimestamp: "2023-12-01T18:29:41Z" + finalizers: + - gateway.finalizer.networking.io + generation: 4 + resourceVersion: "310164667" + uid: ed046878-f659-4908-b80f-b88c9617ba8a + Spec: + gatewayClassName: l7-global-external-managed + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http + port: 80 + protocol: HTTP + Status: + addresses: + - type: IPAddress + value: 10.0.0.1 + conditions: + - lastTransitionTime: "2023-12-01T18:49:25Z" + message: "" + observedGeneration: 3 + reason: Programmed + status: "True" + type: Programmed + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: "2023-12-01T18:49:25Z" + message: Some message + observedGeneration: 3 + reason: Ready + status: "True" + type: Ready + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + AttachedRoutes: + Kind Name Namespace + ---- ---- --------- + HTTPRoute demo-health-check-1 default + TCPRoute demo-retry-policy-1 default + DirectlyAttachedPolicies: + TYPE NAME + ---- ---- + TimeoutPolicy.foo.com demo-timeout-policy-on-gatewayclass + RetryOnPolicy.baz.com demo-retry-policy-1 + InheritedPolicies: + TYPE NAME TARGET KIND TARGET NAME + ---- ---- ----------- ----------- + TimeoutPolicy.foo.com demo-timeout-policy-on-gatewayclass GatewayClass abc-gatewayclass + EffectivePolicies: + HealthCheckPolicy.foo.com: + sampleParentField: + sampleField: hello + RetryOnPolicy.foo.com: + sampleParentField: + sampleField: namaste + TimeoutPolicy.bar.com: + timeout1: parent + timeout2: child + timeout3: parent + timeout4: child + Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal SYNC 2m12s (x46 over 138m) sc-gateway-controller SYNC on default/demo-gateway was a success + ``` + +* `gwctl describe httproute demo-httproute` + ``` + Name: demo-httproute + Namespace: default + Labels: + Annotations: + API Version: gateway.networking.k8s.io/v1beta1 + Kind: HTTPRoute + Metadata: + creationTimestamp: "2023-11-09T09:45:03Z" + generation: 1 + resourceVersion: "290416533" + uid: 716d9e5f-f57a-4e56-81f6-c579d5d17471 + Spec: + hostnames: + - example.com + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: demo-gateway + rules: + - backendRefs: + - group: "" + kind: Service + name: demo-svc + port: 80 + weight: 1 + matches: + - path: + type: PathPrefix + value: /example + Status: + parents: + - conditions: + - lastTransitionTime: "2023-12-01T18:49:14Z" + message: "" + observedGeneration: 1 + reason: ReconciliationSucceeded + status: "True" + type: Reconciled + controllerName: networking.io/gateway + parentRef: + group: gateway.networking.k8s.io + kind: Gateway + name: demo-gateway + DirectlyAttachedPolicies: + TYPE NAME + ---- ---- + HealthCheckPolicy.foo.com demo-health-check-1 + RetryOnPolicy.baz.com demo-retry-policy-1 + InheritedPolicies: + TYPE NAME TARGET KIND TARGET NAME + ---- ---- ----------- ----------- + TimeoutPolicy.foo.com demo-timeout-policy-on-gatewayclass GatewayClass abc-gatewayclass + RetryOnPolicy.baz.com demo-retry-policy-1 Gateway abc-gateway + EffectivePolicies: + HealthCheckPolicy.foo.com: + sampleParentField: + sampleField: hello + RetryOnPolicy.foo.com: + sampleParentField: + sampleField: namaste + TimeoutPolicy.bar.com: + timeout1: parent + timeout2: child + timeout3: parent + timeout4: child + Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal SYNC 2m12s (x46 over 138m) sc-gateway-controller SYNC on default/demo-gateway was a success + ``` + +* `gwctl describe gatewayclass foo-com-external-gateway-class` + ``` + Name: foo-com-external-gateway-class + Labels: + Annotations + API Version gateway.networking.k8s.io/v1beta1 + Kind: GatewayClass + Metadata: + creationTimestamp: "2023-06-28T17:33:03Z" + generation: 1 + resourceVersion: "108322484" + uid: 80cea521-5416-41c4-b5d1-2ee30f5366a6 + ControllerName: foo.com/external-gateway-class + Description: Create an external load balancer + Status: + conditions: + - lastTransitionTime: "2023-05-22T17:29:47Z" + message: "" + observedGeneration: 1 + reason: Accepted + status: "True" + type: Accepted + DirectlyAttachedPolicies: + TYPE NAME + ---- ---- + TimeoutPolicy.bar.com demo-timeout-policy-on-gatewayclass + ``` diff --git a/site-src/ko/geps/gep-2722/metadata.yaml b/site-src/ko/geps/gep-2722/metadata.yaml new file mode 100644 index 0000000000..ca93c3d4ee --- /dev/null +++ b/site-src/ko/geps/gep-2722/metadata.yaml @@ -0,0 +1,15 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 2722 +name: Goals and UX for gwctl +status: Memorandum +authors: + - gauravkghildiyal + - robscott +relationships: + seeAlso: + - number: 713 + name: Metaresources and Policy Attachment + description: Explains the meaning of a Policy and calls out the idea of building a kubectl plugin or command-line tool. +changelog: + - https://github.com/kubernetes-sigs/gateway-api/pull/2723 diff --git a/site-src/ko/geps/gep-2907/index.md b/site-src/ko/geps/gep-2907/index.md new file mode 100644 index 0000000000..a44451bde2 --- /dev/null +++ b/site-src/ko/geps/gep-2907/index.md @@ -0,0 +1,276 @@ +# GEP-2907: TLS Configuration Placement and Terminology + +* Issue: [#2907](https://github.com/kubernetes-sigs/gateway-api/issues/2907) +* Status: Memorandum + +## TLDR +This GEP aims to define high level TLS terminology and structure within Gateway +API to ensure that all our independent proposals related to TLS result in a +coherent set of APIs. This will result in some adjustments to provisional and +experimental TLS-related GEPs, specifically [BackendTLSPolicy](../gep-1897/index.md) +and [Client Certificate Verification](../gep-91/index.md). + +## Goals +* Define high-level terminology for how we refer to TLS in Gateway API. +* Define top level fields where TLS configuration can live. + +## Non-Goals +* Add or change fields directly. (This may inspire changes in other GEPs + though). +* Commit to including specific parts of TLS configuration in Gateway API. (This + is merely to provide space for future configuration, not a commitment that we + will add it to the API.) + +## Out of Scope +There are a variety of related TLS concepts in Gateway API that are not currently +in scope for this GEP. In the future, this GEP may be expanded to include: + +1. Automatic mTLS (often associated with Service mesh) +2. TLSRoute + +## Introduction + +### Where TLS could be configured +We have three different places where we might want to configure TLS: + +#### A. Gateways +Config attached at this layer will apply to everything behind a single address +such as a virtual IP. + +#### B. Gateway Listeners +Each Gateway contains multiple “Listeners”. Each HTTPS Listener in a Gateway +must have a unique combination of protocol, port, and SNI (Server Name +Indication). TLS configuration attached at this layer should be [isolated via +SNI](../../guides/implementers.md#listener-isolation). + +#### C. BackendTLSPolicy +This policy allows us to attach unique TLS configuration per Backend. Depending +on the organization, this policy may be owned by the application owner or the +cluster operator. Note that this configuration will be used by all Gateways +(potentially from different implementations) that are connecting to the backend. + +### "Frontend" and "Backend" +A guiding principle in this naming is to use consistent naming for “Downstream” +(1+2) and “Upstream” (3+4), similar to Envoy. To avoid the confusion with what +is upstream and downstream, Gateway API will use “Frontend” (1+2) and “Backend” +(3+4). + +* **Frontend:** The entity connecting to a Gateway, typically a client + application and/or web browser. +* **Backend:** The entity a Gateway is routing traffic to, typically the + endpoints behind a Service. + +There are essentially 4 different segments that could be relevant to TLS +configuration in Gateway API: + +```mermaid +flowchart LR + Frontend -.->|1. Client Cert| Gateway + Gateway -.->|2. Server Cert| Frontend + Gateway -.->|3. Client Cert| Backend + Backend -.->|4. Server Cert| Gateway +``` + +The above diagram depicts these four segments as edges in a graph. + +### TLS mode + +TLS can be configured with two distinct modes: + +* **Terminate**: the TLS connection is instantiated between the frontend and the + Gateway. The connection between the Gateway and the backend is left unencrypted + unless a new TLS connection between the two entities is configured via BackendTLSPolicy. +* **Passthrough**: the TLS connection is instantiated between the frontend and the + backend. The traffic flows through the Gateway encrypted, and the Gateway is not + able to decrypt or inspect the encrypted portions of the TLS stream. + +## Proposed Segments +Note that this does not represent any form of commitment that any of these +fields or concepts will exist within Gateway API. If or when they do, we propose +the following naming structure: + +### 1. Validate Client Certificate provided by Frontend + +| Proposed Placement | Name | Status | +|-|-|-| +| Gateway Listener | `Listener.TLS.FrontendValidation` | Proposed | + +#### Rationale +Use FrontendValidation to leave room for concepts like trust anchors and trust +domains. Anything not strictly tied to validation would belong to Listener.TLS +which is now reserved exclusively for “Frontend” TLS configuration (1+2). + +#### Why Not Frontend.Validation? +Part of the idea behind this GEP is that Listener.TLS is really entirely focused +on 1+2 - the bits of TLS between frontend and Gateway. That means that if we +were to add any additional TLS configuration in the Listener.TLS struct, it +would tied to that limited scope, and thus we don't really need a separate +Frontend struct. + +One could make an argument that Listener.TLS.Validation should be the field name +here to avoid any ambiguity, but in this specific context, we think that it's +probably helpful to specifically spell out frontend. + +#### Why Not FrontendTLSPolicy? +It could be reasonable to try to mirror BackendTLSPolicy for Frontend TLS. As we +considered that possibility, we evaluated why BackendTLSPolicy exists as a +separate policy resource: + +1. Some parts of the config, such as the SNI that should be used to connect to + the Service/backend only make sense when attached per Service - it's very + unlikely that you'd want to use the same SNI to connect to all backends from + a Gateway. +1. The Service API is overloaded and very slow to change, Gateway API has taken + the approach of exposing config at that level via policy resources that are + tied to specific personas (why Session Persistence config and Backend TLS are + in different resources). + +We don't think either of those reasons really apply to frontend TLS. Instead, +frontend TLS could theoretically be configured either for an entire Gateway, or +a specific Gateway listener. Given that many implementations already support +distinguishing this config per SNI, it seems to make sense to start with +listener level attachment. We think that the persona that would be responsible +for a Gateway is not sufficiently different than the persona that would be +responsible for frontend TLS, so the current proposal is likely the best option +available to us. + +### 2. Configure TLS Termination, including Server Certificate + +| Proposed Placement | Name | Status | +|-|-|-| +| Gateway Listener | `Listener.TLS` | GA | + +#### Rationale +This is already finalized in the API and so we're stuck with this name. In +hindsight a name that was more clearly tied to frontend TLS would have been +ideal here. + +### 3. Configure Client Certificate that Gateway should use to connect to Backend + +| Proposed Placement | Name | Status | +|-|-|-| +| Gateway | `Gateway.Spec.BackendTLS.ClientCertificateRef` | Not Proposed | +| BackendTLSPolicy | `BackendTLSPolicy.Spec.ClientCertificateRef` | Not Proposed | + +#### Rationale +It's not yet obvious which of the above options are preferable, but a case could +be made for either or both. If we add a `BackendTLS` struct to Gateway it would +leave room for concepts like TLS version, ALPN, cipher suites, etc. + +#### Why Not Listener level to match FrontendValidation? +In general, we'd expect this identity to represent a Gateway as a whole, and +thus per-Listener configuration probably does not make sense here. Having +FrontendValidation at the Listener level allows a Gateway to accept different +client certs per SNI (a matching attribute of the frontend -> Gateway +connection). On the other hand, when determining the identity a Gateway should +use when connecting to a backend, it should likely either be tied directly to +the Gateway or Backend, but the Listener is not particularly relevant in this +context. + +### 4. Validate Server Certificate that is provided by Backend +| Proposed Placement | Name | Status | +|-|-|-| +| Gateway | `Gateway.Spec.BackendTLS.Validation` | Not Proposed | +| BackendTLSPolicy | `BackendTLSPolicy.Spec.Validation` | Experimental (Different Name) | + +#### Rationale +Rename `BackendTLSPolicy.TLS` to `BackendTLSPolicy.Validation`. Because this is +already clearly backend-focused, config like TLS Version, ALPN, and cipher +suites, could live at the same level without confusion. It's also plausible that +some Gateways may want to express Gateway-wide CAs that are trusted. + +#### Why BackendTLS on Gateways? +Although this GEP is intentionally not committing to adding new fields or +features, it's possible that at some point in the future we may want to have +some kind of Backend TLS config at the Gateway level. For example, it may be +useful to configure a set of CAs that a Gateway trusts or a client cert that a +Gateway should use to connect to all backends. If this existed, there would +likely be some overlap in config with BackendTLSPolicy, and if a future GEP +proposed this, it would need to include how overlapping config should be +handled. + +#### Why the inconsistency between Frontend and Backend TLS config on Gateways? +If we were to populate all the possible fields described in this GEP, we'd end +up with the following config on Gateways: + +``` +Gateway.Spec.Listeners.TLS.FrontendValidation +Gateway.Spec.Listeners.TLS +Gateway.Spec.BackendTLS.ClientCertificateRef +Gateway.Spec.BackendTLS.Validation +``` + +This is all tied to the need to provide backwards compatibility with the TLS +config that is already GA on Listeners (`Listener.TLS`). If we were naming that +field today with the broader vision of TLS configuration throughout Gateway API +we would almost certainly choose a more descriptive name that was more clearly +tied to Frontend TLS. Unfortunately we're too late to change that name, but we +can try to make the rest of the terminology clearly tied to frontend or backend +TLS. + +One [suggestion by @candita](https://github.com/kubernetes-sigs/gateway-api/pull/2910#discussion_r1552534017) +would be to introduce a Listener like resource for BackendTLS, resulting in a +more consistent naming scheme within Gateway TLS configuration. Although it's +not yet clear if we need this additional layer, we should reconsider it as we're +further developing Backend TLS. + +### 5. Configure TLS mode + +| Proposed Placement | Name | Status | +|-|-|-| +| Gateway Listener | `Listener.TLS.Mode` | GA | + +#### Rationale + +Similarly to the broader [TLS termination](#2-configure-tls-termination-including-server-certificate) +segment, this field is already finalized in the API. In hindsight, along with a +different naming of `Listener.TLS`, we could have moved this field out of the broader +frontend TLS configuration, as it is not bound to it. + +#### How the TLS configuration is affected + +The TLS mode affects how the frontend TLS should be configured. In case `Terminate` +is set, the `Listener.TLS.CertificateRefs` field has to be populated, as the connection +is intended to be terminated at the Gateway level, while for `Passthrough`, the Certificate +does not need to be provided, as the TLS termination is handled by the backend. + +## Routes and TLS + +Multiple routes can be attached to listeners specifying TLS configuration. This section +intends to clearly state how and when Routes can attach to listeners with TLS configuration. + +### Context + +The `*Route` objects refer the Gateway (or a specific Listener of the Gateway) they +want to be attached to. A successful attachment can be granted by one of the two +following conditions: + +* the `Listener.AllowedRoutes` field allows that specific Route `GroupKind` to be + attached to it, or +* the `Listener.Protocol` field allows that specific Route to be attached to the + Listener. This applies only in case the Gateway's AllowedRoutes field is not set. + +In case the First condition is not satisfied (the Route references a Gateway that +does not explicitly allow such an attachment), the Route `Accepted` condition +is set to False with reason `NotAllowedByListeners`. In case the Route references +a Gateway with no Listener matching the protocol needed by the Route, the Route +`ResolvedRefs` condition is set to False with reason `UnsupportedProtocol`. + +### What Routes are allowed by Listeners with TLS + +The following is a summary of all the Routes and the TLS termination mode they support, along +with the compatible protocol. + +| Protocol | Routes | TLS Terminate | TLS Passthough | +|-----------|---------|---------------|----------------| +| HTTP | `HTTPRoute`/`GRPCRoute` | no | no | +| HTTPS | `HTTPRoute`/`GRPCRoute` | yes | no | +| TLS | `TLSRoute` | yes | yes | +| TCP | `TCPRoute` | yes | no | +| UDP | `UDPRoute` | no | no | + +> [!NOTE] +> When the traffic is routed to the backend via a listener configured with TLS `Passthrough` +> and a compatible route, the packets are left untouched by the gateway. In order to +> terminate the TLS connection to the gateway and forward the traffic unencrypted to the backend, +> a listener configured with TLS `Terminate` and a compatible route must be used. diff --git a/site-src/ko/geps/gep-2907/metadata.yaml b/site-src/ko/geps/gep-2907/metadata.yaml new file mode 100644 index 0000000000..0a5cd84c21 --- /dev/null +++ b/site-src/ko/geps/gep-2907/metadata.yaml @@ -0,0 +1,15 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 2907 +name: TLS Configuration Placement and Terminology +status: Memorandum +authors: + - robscott +relationships: + seeAlso: + - number: 91 + name: Client Certificate Verification for Gateway Listeners + description: Will use some of the terminology defined by this GEP. + - number: 1897 + name: TLS from Gateway to Backend + description: Will use some of the terminology defined by this GEP. diff --git a/site-src/ko/geps/gep-3155/index.md b/site-src/ko/geps/gep-3155/index.md new file mode 100644 index 0000000000..b75b64cccf --- /dev/null +++ b/site-src/ko/geps/gep-3155/index.md @@ -0,0 +1,196 @@ +# GEP-3155: Complete Backend mutual TLS Configuration + +* Issue: [#3155](https://github.com/kubernetes-sigs/gateway-api/issues/3155) +* Status: Experimental + +## TLDR + +This GEP aims to complete the configuration required for Backend mutual TLS in Gateway +API. This includes the following new capabilities: + +1. Configuration for the client certificate Gateways should use when connecting + to Backends +1. Ability to specify SANs on BackendTLSPolicy +1. Add TLS options to BackendTLSPolicy to mirror TLS config on Gateways + +## Goals + +* Add sufficient configuration that basic mutual TLS is possible between Gateways and + Backends +* Enable the optional use of SPIFFE for Backend mutual TLS + +## Non-Goals + +* Define how automatic mTLS should be implemented with Gateway API + +## Introduction + +This is a wide ranging GEP intending to cover three additions to the API that all +have a shared goal - enabling backend mutual TLS with Gateway API. Although this +specific GEP focuses on manual configuration across the board, the hope is that +it will also enable higher level automation to simplify this process for users. + +## API + +### Client Certs on Gateways + +A key requirement of mutual TLS is that the Gateway can provide a client cert to the +backend. This adds that configuration to both Gateway and Service (via +BackendTLSPolicy). + +#### Gateway-level (Core support) +Specifying credentials at the gateway level is the default operation mode, where all +backends will be presented with a single gateway certificate. Per-service overrides are +subject for consideration as the future work. + +**1. Add a new `BackendTLS` field at the top level of Gateways** + +```go +type GatewaySpec struct { + // BackendTLS configures TLS settings for when this Gateway is connecting to + // backends with TLS. + BackendTLS GatewayBackendTLS `json:"backendTLS,omitempty"'` +} +type GatewayBackendTLS struct { + // ClientCertificateRef is a reference to an object that contains a Client + // Certificate and the associated private key. + // + // References to a resource in different namespace are invalid UNLESS there + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. If a ReferenceGrant does not allow this reference, the + // "ResolvedRefs" condition MUST be set to False for this listener with the + // "RefNotPermitted" reason. + // + // ClientCertificateRef can reference to standard Kubernetes resources, i.e. + // Secret, or implementation-specific custom resources. + // + // This setting can be overridden on the service level by use of BackendTLSPolicy. + ClientCertificateRef SecretObjectReference `json:"clientCertificateRef,omitempty"` +} +``` + +### SANs on BackendTLSPolicy + +This change enables the backend certificate to have a different identity than the SNI +(both are currently tied to the hostname field). This is particularly useful +when using SPIFFE, which relies on URI Subject Names which are not valid SNIs +as per https://www.rfc-editor.org/rfc/rfc6066.html#section-3. + +In such case either connection properties or an arbitrary SNI, like cluster-local +service name could be used for certificate selection, while the identity validation +will be done based on SubjectAltNames field. + +When specified, the certificate served from the backend MUST have at least one Subject +Alternate Name matching one of the specified SubjectAltNames. + + + +**1. Add a new `SubjectAltNames` field to `BackendTLSPolicyValidation`** + +```go +type BackendTLSPolicyValidation struct { + // SubjectAltNames contains one or more Subject Alternative Names. + // When specified, the certificate served from the backend MUST have at least one + // Subject Alternate Name matching one of the specified SubjectAltNames. + // +kubebuilder:validation:MaxItems=5 + SubjectAltNames []SubjectAltName `json:"subjectAltNames,omitempty"` +} + +// +kubebuilder:validation:Enum=Cookie;Header +type SubjectAltNameType string + +const ( + // HostnameSubjectAltNameType specifies hostname-based SAN. + // + // Support: Core + HostnameSubjectAltNameType SubjectAltNameType = "Hostname" + + // URISubjectAltNameType specifies URI-based SAN, e.g. SPIFFE id. + // + // Support: Core + URISubjectAltNameType SubjectAltNameType = "URI" +) + + +type SubjectAltName struct { + // Type determines the format of the Subject Alternative Name. Always required. + Type SubjectAltNameType `json:"type"` + + // Hostname contains Subject Alternative Name specified in DNS name format. Required when Type is set to Hostname, ignored otherwise. + Hostname v1.PreciseHostname `json:"hostname,omitempty"` + + // URI contains Subject Alternative Name specified in URI format. Required when Type is set to URI, ignored otherwise. + URI string `json:"uri,omitempty"` +} +``` + +**2. Modify Spec for `BackendTLSPolicyValidation` `Hostname`** + +Before: +```go + // 2. Hostname MUST be used for authentication and MUST match the certificate + // served by the matching backend. +``` + +After: +```go + // 2. Only if SubjectAltNames is not specified, Hostname MUST be used for + // authentication and MUST match the certificate served by the matching + // backend. +``` + +### Allow per-service TLS settings BackendTLSPolicy + +Gateway level TLS configuration already includes an `options` field. This has +been helpful for implementation-specific TLS configurations, or simply features +that have not made it to the core API yet. It would be similarly useful to have +an identical field on BackendTLSPolicy. + +Examples: +- configuration options for vendor-specific mTLS automation +- restrictions on the minimum supported TLS version or supported cipher suites + +```go +type BackendTLSPolicySpec struct { + // Options are a list of key/value pairs to enable extended TLS + // configuration for each implementation. For example, configuring the + // minimum TLS version or supported cipher suites. + // + // A set of common keys MAY be defined by the API in the future. To avoid + // any ambiguity, implementation-specific definitions MUST use + // domain-prefixed names, such as `example.com/my-custom-option`. + // Un-prefixed names are reserved for key names defined by Gateway API. + // + // Support: Implementation-specific + // + // +optional + // +kubebuilder:validation:MaxProperties=16 + Options map[AnnotationKey]AnnotationValue `json:"options,omitempty"` +} +``` + +## Conformance Details + +Conformance tests will be written to ensure the following: + +1. When SubjectAltNames are specified in BackendTLSPolicy: + - The hostname field is still used as SNI, if specified + - A certificate with at least one matching SubjectAltName is accepted + - A certificate without a matching SubjectAltName is rejected + +2. When a Client Certificate is specified on a Gateway: + - It is applied to all services. + - The appropriate status condition is populated if the reference is invalid + +## Future work +This GEP does not cover per-service overrides for client certificate. This is mostly for two reasons: + +- it supports only the niche use cases - it should be reconsidered in future +- in current model, where BackendTLSPolicy shares namespace with the service instead of the Gateway, there are non-trivial security implications to adding client certificate configuration at this level - therefore ownership and colocation of BackendTLSPolicy (Service vs Gateway) needs to be figured out first + +## References + +This is a natural continuation of +[GEP-2907](../gep-2907/index.md), the memorandum GEP +that provided the overall vision for where TLS configuration should fit +throughout Gateway API. diff --git a/site-src/ko/geps/gep-3155/metadata.yaml b/site-src/ko/geps/gep-3155/metadata.yaml new file mode 100644 index 0000000000..6e0528817c --- /dev/null +++ b/site-src/ko/geps/gep-3155/metadata.yaml @@ -0,0 +1,15 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 3155 +name: Complete Backend mutual TLS Configuration +status: Experimental +authors: + - mkosieradzki + - robscott +featureNames: + - BackendTLSPolicySANs +relationships: + seeAlso: + - number: 2907 + name: TLS Configuration Placement and Terminology + description: Will use some of the terminology defined by this GEP. diff --git a/site-src/ko/geps/gep-3171/index.md b/site-src/ko/geps/gep-3171/index.md new file mode 100644 index 0000000000..631223f2fb --- /dev/null +++ b/site-src/ko/geps/gep-3171/index.md @@ -0,0 +1,217 @@ +# GEP-3171: Percentage-based Request Mirroring + +* Issue: [#3171](https://github.com/kubernetes-sigs/gateway-api/issues/3171) +* Status: Standard + +(See [status definitions](../overview.md#gep-states).) + +## TLDR + +Enhance the existing [Request Mirroring](../../guides/http-request-mirroring.md) feature by allowing users to specify a percentage of requests they'd like mirrored. + +## Goals + +Enable percentage-based request mirroring with Gateway and Gateway for mesh APIs. + +## Scope + + +The scope of this GEP is to add support for this feature in both HTTPRoute and GRPCRoute + +## Introduction + +[Request Mirroring](../../guides/http-request-mirroring.md) is a feature that allows a user to mirror requests going to some backend A along to some other specified backend B. Right now Request Mirroring is an all or nothing feature – either 100% of request are mirrored, or 0% are. Percentage-based Request Mirroring will allow users to specify a percentage of requests they'd like mirrored as opposed to every single request. + +This feature is already [supported by Envoy][config.route.v3.RouteAction.RequestMirrorPolicy], so adding it for the Gateway API would enable better integration between the two products. There's also an existing user desire for this feature on the [HAProxy side](https://www.haproxy.com/blog/haproxy-traffic-mirroring-for-real-world-testing) and [NGINX side](https://alex.dzyoba.com/blog/nginx-mirror/). Since Request Mirroring is already supported by the Gateway API, Percentage-based Request Mirroring would a clear improvement on this preexisting feature. + +[config.route.v3.RouteAction.RequestMirrorPolicy]: https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-routeaction-requestmirrorpolicy + +## Existing Support in Implementations + +| Implementation | Support | +|----------------|------------| +| Envoy | [config.route.v3.RouteAction.RequestMirrorPolicy][config.route.v3.RouteAction.RequestMirrorPolicy] | +| HAProxy | [HAProxy SPOP](https://github.com/haproxytech/spoa-mirror) | +| NGINX | [ngx_http_mirror_module](https://nginx.org/en/docs/http/ngx_http_mirror_module.html) | + + +## API + +This GEP proposes the following API changes: + +* Add utility type `Fraction` to [v1/shared_types.go](https://github.com/kubernetes-sigs/gateway-api/blob/cb5bf1541fa70f0692aebde8c64bba434cf331b6/apis/v1/shared_types.go): + + +```go +type Fraction struct { + // +optional + // +kubebuilder:default=100 + // +kubebuilder:validation:Minimum=0 + Numerator int32 `json:"numerator"` + + // +optional + // +kubebuilder:default=100 + // +kubebuilder:validation:Minimum=1 + Denominator int32 `json:"denominator"` +} +``` + + +* Update the `HTTPRequestMirrorFilter` struct to include a `Percent` field of type `int32`, and a `Fraction` field of type `Fraction`: + + +```go +// HTTPRequestMirrorFilter defines configuration for the RequestMirror filter. +type HTTPRequestMirrorFilter struct { + // BackendRef references a resource where mirrored requests are sent. + // + // Mirrored requests must be sent only to a single destination endpoint + // within this BackendRef, irrespective of how many endpoints are present + // within this BackendRef. + // + // If the referent cannot be found, this BackendRef is invalid and must be + // dropped from the Gateway. The controller must ensure the "ResolvedRefs" + // condition on the Route status is set to `status: False` and not configure + // this backend in the underlying implementation. + // + // If there is a cross-namespace reference to an *existing* object + // that is not allowed by a ReferenceGrant, the controller must ensure the + // "ResolvedRefs" condition on the Route is set to `status: False`, + // with the "RefNotPermitted" reason and not configure this backend in the + // underlying implementation. + // + // In either error case, the Message of the `ResolvedRefs` Condition + // should be used to provide more detail about the problem. + // + // Support: Extended for Kubernetes Service + // + // Support: Implementation-specific for any other resource + BackendRef BackendObjectReference `json:"backendRef"` + + // Percent represents the percentage of requests that should be + // mirrored to BackendRef. Its minimum value is 0 (indicating 0% of + // requests) and its maximum value is 100 (indicating 100% of requests). + // + // If both Percent and Fraction are specified, Fraction will take + // priority. If Percent is unspecified, it will have a default value of + // 100. If Fraction is unspecified, it will have a default value of + // 100/100. This means that if neither field is specified, 100% of + // requests will be mirrored. + // + // +optional + // +kubebuilder:default=100 + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=100 + Percent int32 `json:"percent,omitempty"` + + // Fraction represents the fraction of requests that should be + // mirrored to BackendRef. + // + // If both Percent and Fraction are specified, Fraction will take + // priority. If Percent is unspecified, it will have a default value of + // 100. If Fraction is unspecified, it will have a default value of + // 100/100. This means that if neither field is specified, 100% of + // requests will be mirrored. + // + // +optional + Fraction Fraction `json:"fraction,omitempty"` +} +``` + +## Examples for North/South traffic + +An example with Percent: + + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-filter-mirror + labels: + gateway: mirror-gateway +spec: + parentRefs: + - name: mirror-gateway + hostnames: + - mirror.example + rules: + - backendRefs: + - name: foo-v1 + port: 8080 + filters: + - type: RequestMirror + requestMirror: + backendRef: + name: foo-v2 + port: 8080 + percent: 42 +``` + +This would result in 42% of requests going to `foo-v1` to be mirrored to `foo-v2`. + +An example with Fraction: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-filter-mirror + labels: + gateway: mirror-gateway +spec: + parentRefs: + - name: mirror-gateway + hostnames: + - mirror.example + rules: + - backendRefs: + - name: foo-v1 + port: 8080 + filters: + - type: RequestMirror + requestMirror: + backendRef: + name: foo-v2 + port: 8080 + fraction: + numerator: 5 + denominator: 1000 +``` + +This would result in 0.5% of requests going to `foo-v1` to be mirrored to `foo-v2`. + +## Examples for East/West traffic + +Similarly, here is how it would be for mesh. + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-filter-mirror + labels: + service: mirror-service +spec: + parentRefs: + - group: "" + kind: Service + name: mirror-service + rules: + - backendRefs: + - name: foo-v1 + port: 8080 + filters: + - type: RequestMirror + requestMirror: + backendRef: + name: foo-v2 + port: 8080 + percent: 42 +``` + +## Conformance Details + +A new Supported Feature with the following name SupportHTTPRouteRequestPercentageMirror is introduced along with a corresponding conformance test. + + diff --git a/site-src/ko/geps/gep-3171/metadata.yaml b/site-src/ko/geps/gep-3171/metadata.yaml new file mode 100644 index 0000000000..3b4d54fc26 --- /dev/null +++ b/site-src/ko/geps/gep-3171/metadata.yaml @@ -0,0 +1,16 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha2 +kind: GEPDetails +number: 3171 +name: Percentage-based Request Mirroring +status: Standard +authors: + - jakebennert + - LiorLieberman +references: + - https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.HTTPRequestMirrorFilter + - https://github.com/kubernetes-sigs/gateway-api/pull/3199 + - https://github.com/kubernetes-sigs/gateway-api/pull/3301 + - https://github.com/kubernetes-sigs/gateway-api/pull/3638 + - https://github.com/kubernetes-sigs/gateway-api/pull/3508 +featureNames: + - HTTPRouteRequestPercentageMirror diff --git a/site-src/ko/geps/gep-3388/index.md b/site-src/ko/geps/gep-3388/index.md new file mode 100644 index 0000000000..6d0227e4d6 --- /dev/null +++ b/site-src/ko/geps/gep-3388/index.md @@ -0,0 +1,248 @@ +# GEP-3388: Retry Budgets + +* Issue: [#3388](https://github.com/kubernetes-sigs/gateway-api/issues/3388) +* Status: Experimental + +(See [status definitions](../overview.md#gep-states).) + +## TLDR + +To allow configuration of a "retry budget" across all endpoints of a destination service, preventing additional client-side retries when the percentage of the active request load consisting of retries reaches a certain threshold. + +## Goals + +* To allow specification of a retry ["budget"](https://finagle.github.io/blog/2016/02/08/retry-budgets/) to determine whether a request should be retried, and any shared configuration or interaction with configuration of a static retry limit within HTTPRoute. +* To allow specification of a percentage of active requests, or recently active requests, that should be able to be retried concurrently. +* To allow specification of a *minimum* number of retries that should be allowed per second or concurrently, such that the budget for retries never goes below this minimum value. +* To define a standard for retry budgets that reconciles the known differences in current retry budget functionality between Gateway API data plane implementations. + +## Non-Goals + +* To allow specifying a default retry budget policy across a namespace or attached to a specific gateway. +* To allow configuration of a back-off strategy or timeout window within the retry budget spec. +* To allow specifying inclusion of specific HTTP status codes and responses within the retry budget spec. +* To allow specification of more than one retry budget for a given service, or for specific subsets of its traffic. + +## Introduction + +Multiple data plane proxies offer optional configuration for budgeted retries, in order to create a dynamic limit on the amount of a service's active request load that is comprised of retries from across its clients. In the case of Linkerd, retry budgets are the default retry policy configuration for HTTP retries within the [ServiceProfile CRD](https://linkerd.io/2.12/reference/service-profiles/), with static max retries being a [fairly recent addition](https://linkerd.io/2024/08/13/announcing-linkerd-2.16/). + +Configuring a limit for client retries is an important factor in building a resilient system, allowing requests to be successfully retried during periods of intermittent failure. But too many client-side retries can also exacerbate consistent failures and slow down recovery, quickly overwhelming a failing system and leading to cascading failures such as retry storms. Configuring a sane limit for max client-side retries is often challenging in complex systems. Allowing an application developer (Ana) to configure a dynamic "retry budget" reduces the risk of a high number of retries across clients. It allows a service to perform as expected in both times of high & low request load, as well as both during periods of intermittent & consistent failures. + +While retry budget configuration has been a frequently discussed feature within the community, differences in the semantics between data plane implementations creates a challenge for a consensus on the correct location for the configuration. This proposal aims to determine where retry budgets should be defined within the Gateway API, and whether data plane proxies may need to be altered to accommodate the specification. + +### Background on implementations + +#### Envoy + +Envoy offers retry budgets as a configurable circuit breaker threshold for concurrent retries to an upstream cluster, in favor of configuring a static max retry threshold. In Istio, Envoy circuit breaker thresholds are typically configured [within the DestinationRule CRD](https://istio.io/latest/docs/reference/config/networking/destination-rule/#ConnectionPoolSettings-HTTPSettings), which applies rules to clients of a service after routing has already occurred. + +The optional [RetryBudget](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/circuit_breaker.proto#envoy-v3-api-msg-config-cluster-v3-circuitbreakers-thresholds-retrybudget) CircuitBreaker threshold can be configured with the following parameters: + +* `budget_percent` Specifies the limit on concurrent retries as a percentage of the sum of active requests and active pending requests. For example, if there are 100 active requests and the budget_percent is set to 25, there may be 25 active retries. This parameter is optional. Defaults to 20%. + +* `min_retry_concurrency` Specifies the minimum retry concurrency allowed for the retry budget. The limit on the number of active retries may never go below this number. This parameter is optional. Defaults to 3. + +By default, Envoy uses a static threshold for retries. But when configured, Envoy's retry budget threshold overrides any other retry circuit breaker that has been configured. + +#### linkerd2-proxy + +The Linkerd implementation of retry budgets is configured alongside service route configuration, within the [ServiceProfile CRD](https://linkerd.io/2.12/reference/service-profiles/), limiting the number of total retries for a service as a percentage of the number of recent requests. In practice, this functions similarly to Envoy's retry budget implementation, as it is configured in a single location and measures the ratio of retry requests to original requests across all traffic destined for the service. + +(Note that budgeted retries have become less commonly used since Linkerd added support for counted retries in [edge-24.7.5](https://github.com/linkerd/linkerd2/releases/tag/edge-24.7.5): ServiceProfile operates at the level of a backend workload, meaning that it cannot configure anything at the level of a route, but counted retries can be configured using annotations on Service, HTTPRoute, and GRPCRoute.) + +For both counted retries and budgeted retries, the actual retry logic is implemented by the `linkerd2-proxy` making the request on behalf on an application workload. The receiving proxy is not aware of the retry configuration at all. + +Linkerd's budgeted retries allow retrying an indefinite number of times, as long as the fraction of retries remains within the budget. Budgeted retries are supported only using Linkerd's native ServiceProfile CRD, which allows enabling retries, setting the retry budget (by default, 20% plus 10 "extra" retries per second), and configuring the window over which the fraction of retries to non-retries is calculated. The `retryBudget` field of the ServiceProfile spec can be configured with the following optional parameters: + +* `retryRatio` Specifies a ratio of retry requests to original requests that is allowed. The default is 0.2, meaning that retries may add up to 20% to the request load. + +* `minRetriesPerSecond` Specifies the minimum rate of retries per second that is allowed, so that retries are not prevented when the request load is very low. The default is 10. + +* `ttl` A duration specifying how long requests are considered for when calculating the retry threshold. The default is 10s. + +### Proposed Design + +#### Retry Budget Policy Attachment + +While current retry behavior is defined at the routing rule level within HTTPRoute, exposing retry budget configuration as a policy attachment offers some advantages: + +* Users could define a single policy, targeting a service, that would dynamically configure a retry threshold based on the percentage of active requests across *all routes* destined for that service's backends. + +* In both Envoy and Linkerd data plane implementations, a retry budget is configured once to match all endpoints of a service, regardless of the routing rule that the request matches on. A policy attachment will allow for a single configuration for a service's retry budget, as opposed to configuring the retry budget across multiple HTTPRoute objects (see [Alternatives](#httproute-retry-budget)). + +* Being able to configure a dynamic threshold of retries at the service level, alongside a static max number of retries on the route level. In practice, application developers would then be allowed more granular control of which requests should be retried. For example, an application developer may not want to perform retries on a specific route where requests are not idempotent, and can disable retries for that route. By having a retry budget policy configured, retries from other routes will still benefit from the budgeted retries. + +Configuring a retry budget through a Policy Attachment may produce some confusion from a UX perspective, as users will be able to configure retries in two different places (HTTPRoute for static retries, versus a policy attachment for a dynamic retry threshold). Though this is likely a fair trade-off. + +Discrepancies in the semantics of retry budget behavior and configuration options between Envoy and Linkerd may require a change in either implementation to accommodate the Gateway API specification. While Envoy's `min_retry_concurrency` setting may behave similarly in practice to Linkerd's `minRetriesPerSecond`, they are not directly equivalent. + +The implementation of a version of Linkerd's `ttl` parameter within Envoy might be a path towards reconciling the behavior of these implementations, as it could allow Envoy to express a `budget_percent` and minimum number of permissible retries over a period of time rather than by tracking active and pending connections. It is not currently clear which of these models is preferable, but being able to specify a budget as requests over a window of time seems like it might offer more predictable behavior. + +## API + +### Go + +```golang +type BackendTrafficPolicy struct { + // BackendTrafficPolicy defines the configuration for how traffic to a target backend should be handled. + // + // Support: Extended + // + // +optional + // + // + // Note: there is no Override or Default policy configuration. + + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of BackendTrafficPolicy. + Spec BackendTrafficPolicySpec `json:"spec"` + + // Status defines the current state of BackendTrafficPolicy. + Status PolicyStatus `json:"status,omitempty"` +} + +type BackendTrafficPolicySpec struct { + // TargetRef identifies an API object to apply policy to. + // Currently, Backends (i.e. Service, ServiceImport, or any + // implementation-specific backendRef) are the only valid API + // target references. + // +listType=map + // +listMapKey=group + // +listMapKey=kind + // +listMapKey=name + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=16 + TargetRefs []LocalPolicyTargetReference `json:"targetRefs"` + + // Retry defines the configuration for when to retry a request to a target backend. + // + // Implementations SHOULD retry on connection errors (disconnect, reset, timeout, + // TCP failure) if a retry stanza is configured. + // + // Support: Extended + // + // +optional + // + Retry *CommonRetryPolicy `json:"retry,omitempty"` + + // SessionPersistence defines and configures session persistence + // for the backend. + // + // Support: Extended + // + // +optional + SessionPersistence *SessionPersistence `json:"sessionPersistence,omitempty"` +} + +// CommonRetryPolicy defines the configuration for when to retry a request. +// +type CommonRetryPolicy struct { + // Support: Extended + // + // +optional + BudgetPercent *Int `json:"budgetPercent,omitempty"` + + // Support: Extended + // + // +optional + BudgetInterval *Duration `json:"budgetInterval,omitempty"` + + // Support: Extended + // + // +optional + MinRetryRate *RequestRate `json:"minRetryRate,omitempty"` +} + +// RequestRate expresses a rate of requests over a given period of time. +// +type RequestRate struct { + // Support: Extended + // + // +optional + Count *Int `json:"count,omitempty"` + + // Support: Extended + // + // +optional + Interval *Duration `json:"interval,omitempty"` +} + +// Duration is a string value representing a duration in time. The format is +// as specified in GEP-2257, a strict subset of the syntax parsed by Golang +// time.ParseDuration. +// +// +kubebuilder:validation:Pattern=`^([0-9]{1,5}(h|m|s|ms)){1,4}$` +type Duration string + +### YAML + +```yaml +apiVersion: gateway.networking.x-k8s.io/v1alpha1 +kind: BackendTrafficPolicy +metadata: + name: traffic-policy-example +spec: + targetRefs: + - group: "" + kind: Service + name: foo + retry: + budgetPercent: 20 + budgetInterval: 10s + minRetryRate: + count: 3 + interval: 1s + sessionPersistence: + ... + status: + ancestors: + - ancestorRef: + kind: Mesh + namespace: istio-system + name: istio + controllerName: "istio.io/mesh-controller" + conditions: + - type: "Accepted" + status: "False" + reason: "Invalid" + message: "BackendTrafficPolicy field sessionPersistence is not supported for Istio mesh traffic." + - ancestorRef: + kind: Gateway + namespace: foo-ns + name: foo-ingress + controllerName: "istio.io/mesh-controller" + conditions: + - type: "Accepted" + status: "False" + reason: "Invalid" + message: "BackendTrafficPolicy fields retry.budgetPercentage, retry.budgetInterval and retry.minRetryRate are not supported for Istio ingress gateways." + ... +``` + +## Conformance Details + +TODO + +## Alternatives + +### HTTPRoute Retry Budget + +* The desired UX for retry budgets is to apply the policy at the service level, rather than individually across each route targeting the service. Placing the retry budget configuration within HTTPRoute would violate this requirement, as separate HTTPRoute objects could each have routing rules targeting the same destination service, and a single HTTPRoute object can target multiple destinations. To apply a retry budget to all routes targeting a service, a user would need to duplicate the configuration across multiple routing rules. + +* If we wanted retry budgets to be configured on a per-route basis (as opposed to at the service level), it would require a change to be made in Envoy Route. And more than likely, similar changes would need to be made for Linkerd. + +## Other considerations + +* As there isn't anything inherently specific to HTTP requests in either known implementation, a retry budget policy on a target Service could likely be applicable to GRPCRoute as well as HTTPRoute requests. +* While retry budgets are commonly associated with service mesh uses cases to handle many distributed clients, a retry budget policy may also be desirable for north/south implementations of Gateway API to prioritize new inbound requests and minimize tail latency during periods of service instability. + +## References + +* +* +* +* +* diff --git a/site-src/ko/geps/gep-3388/metadata.yaml b/site-src/ko/geps/gep-3388/metadata.yaml new file mode 100644 index 0000000000..53b9ef127a --- /dev/null +++ b/site-src/ko/geps/gep-3388/metadata.yaml @@ -0,0 +1,40 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 3388 +name: Retry Budgets +status: Implementable +# Any authors who contribute to the GEP in any way should be listed here using +# their GitHub handle. +authors: + - ericdbishop + - mikemorris +relationships: + # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely + # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field + # set back to this GEP, and MUST be moved to Declined. + obsoletes: {} + obsoletedBy: {} + # extends indicates that a GEP extends the linked GEP, adding more detail + # or additional implementation. The extended GEP MUST have its extendedBy + # field set back to this GEP. + extends: + - number: 1731 + name: HTTPRoute Retries + extendedBy: {} + # seeAlso indicates other GEPs that are relevant in some way without being + # covered by an existing relationship. + seeAlso: {} +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: + - https://github.com/kubernetes-sigs/gateway-api/pull/3607 + - https://github.com/kubernetes-sigs/gateway-api/pull/3488 + - https://github.com/kubernetes-sigs/gateway-api/pull/3682 + - https://github.com/kubernetes-sigs/gateway-api/pull/3692 + - https://github.com/kubernetes-sigs/gateway-api/pull/3695 +# featureNames is a list of the feature names introduced by the GEP, if there +# are any. This will allow us to track which feature was introduced by which GEP. +featureNames: {} +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: {} diff --git a/site-src/ko/geps/gep-3567/index.md b/site-src/ko/geps/gep-3567/index.md new file mode 100644 index 0000000000..c6a4c36f0e --- /dev/null +++ b/site-src/ko/geps/gep-3567/index.md @@ -0,0 +1,162 @@ +# GEP-3567: Gateway TLS Updates for HTTP/2 Connection Coalescing + +* Issue: [#3567](https://github.com/kubernetes-sigs/gateway-api/issues/3567) +* Status: Experimental + +## TLDR + +As described in the [previous +doc](https://docs.google.com/document/d/1g_TNN8eOaVDC3xesO9JFdvQbPFdSTHp1vb70TD3-Vrs/edit?tab=t.0#heading=h.qiz1tfw67tbp), +the current state of TLS configuration on Gateways can lead to confusing +behavior when combined with HTTP/2 connection coalescing. This GEP proposes a +series of changes to the API to address these problems. + +## Goals + +* Take steps that will make it less likely for users to encounter these problems +* Warn when users have configuration that is prone to these issues +* Provide central source of documentation explaining both the problem and + potential solutions + +## Non-Goals + +* Breaking or significantly disruptive changes to the existing API surface + +## Introduction + +Gateway API creates situations where clients might be able to send requests +through a Listener that, according to the Gateway’s configuration, is not +supposed to receive these requests. This can cause requests to be apparently +mis-routed. + +The problem here is an inherent conflict between the API and the mechanics of +HTTPS. Gateway API uses the “hostname” field in the Listener to constrain both +the TLS certificate selection and the host header of requests. But when a server +presents a TLS certificate that is valid for multiple domains, a client is free +to reuse its TLS connection for requests sent to any of those domains (for +HTTP2, see RFC). The SNI hostname, which the client presents only with the +initial TLS handshake, doesn’t constrain the host header of the requests that +the client sends. + +Gateway API deals with this situation imprecisely, stating: + + The Listener Hostname SHOULD match at both the TLS and HTTP protocol layers + as described above. If an implementation does not ensure that both the SNI + and Host header match the Listener hostname, it MUST clearly document that. + +In practice we can end up with an implementation that misroutes requests when a +Gateway is configured using certificates that use multiple or wildcard SANs. + +### Example + +The following configuration ([from the Gateway API +documentation](../../guides/tls.md#wildcard-tls-listeners)) +illustrates the problem: + + +``` +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: wildcard-tls-gateway +spec: + gatewayClassName: example + listeners: + - name: foo-https + protocol: HTTPS + port: 443 + hostname: foo.example.com + tls: + certificateRefs: + - kind: Secret + group: "" + name: foo-example-com-cert # SAN: foo.example.com + - name: wildcard-https + protocol: HTTPS + port: 443 + hostname: "*.example.com" + tls: + certificateRefs: + - kind: Secret + group: "" + name: wildcard-example-com-cert # SAN: *.example.com +``` + + +The Gateway API definition requires requests to `foo.example.com` to be +associated with the `foo-https` listener, on connections negotiated with +`foo-example-com-cert`. + +Suppose a client sends a request to `bar.example.com`, specifying that as the +SNI hostname, and establishes a TLS connection attached to the `wildcard-https` +Listener. And then it sends a subsequent request to `foo.example.com`. The +client can correctly reuse its existing TLS connection for the second request, +because the `wildcard-example-com-cert` is valid also for `foo.example.com`. But +now the Gateway has a problem: Routing the request via the `wildcard-https` +Listener violates the intent of the configuration, and routing via the +`foo-https` Listener is inconsistent with the connection’s having been +negotiated with the other Listener’s certificate. + +Mapping a request to a Listener matters if the Gateway configuration has +different +[HTTPRoutes](../../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRoute) +bound to the different Listeners. It also matters if the Listeners have +different +[GatewayTlsConfigs](../../reference/spec.md#gateway.networking.k8s.io/v1.GatewayTLSConfig) +attached, for example if one Listener uses mutual TLS and the other does not. + + +### Interaction with Client Cert Validation + +[GEP-91](../gep-91/index.md) introduced Client +Certificate Validation to Gateway Listeners as a new experimental concept. If an +implementation is unable to properly isolate HTTPS listeners, this could result +in this Client Cert Validation being bypassed. Before this feature can graduate +beyond experimental, we’ll need to resolve this underlying issue. + +## Proposal + +### A) Add Warning in Gateway Status +A new condition will be added to Gateways: `OverlappingTLSConfig`. +Implementations MUST add this condition to status when a Gateway is configured +with TLS configuration across multiple Listeners. Implementations MAY add this +condition to status when a Gateway is configured with overlapping TLS +certificates. Note that since this is a negative polarity condition, it would +only be populated when it is true. + +### B) Modify API Spec to recommend sending 421s +The Gateway spec for `listener.hostname` will be updated to recommend returning +a 421 when this problem occurs. + +### C) Top Level Gateway TLS Config for Client Cert Validation + +A follow up discussion for GEP-91 will consider if Client Cert Validation should +be moved or copied to a new top level Gateway TLS config instead of +per-listener. + +## Conformance Details + +#### Feature Names + +A) None, this will be required for any implementations that support HTTP + +Gateways. + +B) `GatewayReturn421` + +C) Will be covered in GEP-91 + +### Conformance tests + +A) A new conformance test will be added to ensure that the new status condition +is populated when a Gateway is configured with overlapping TLS configuration. + +B) A new conformance test will be added to ensure that implementations return a +421 when a connection is reused for a different listener with an overlapping +SNI. + +C) Will be covered in GEP-91 + +## Alternatives + +Discussed in more detail the [original +doc](https://docs.google.com/document/d/1g_TNN8eOaVDC3xesO9JFdvQbPFdSTHp1vb70TD3-Vrs/edit?tab=t.0#heading=h.qiz1tfw67tbp) diff --git a/site-src/ko/geps/gep-3567/metadata.yaml b/site-src/ko/geps/gep-3567/metadata.yaml new file mode 100644 index 0000000000..be9f0fd374 --- /dev/null +++ b/site-src/ko/geps/gep-3567/metadata.yaml @@ -0,0 +1,33 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 3567 +name: Gateway TLS Updates for HTTP/2 Connection Coalescing +status: Implementable +# Any authors who contribute to the GEP in any way should be listed here using +# their GitHub handle. +authors: + - robscott +relationships: + # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely + # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field + # set back to this GEP, and MUST be moved to Declined. + obsoletes: {} + obsoletedBy: {} + # extends indicates that a GEP extends the linked GEP, adding more detail + # or additional implementation. The extended GEP MUST have its extendedBy + # field set back to this GEP. + extends: {} + extendedBy: {} + # seeAlso indicates other GEPs that are relevant in some way without being + # covered by an existing relationship. + seeAlso: {} +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: {} +# featureNames is a list of the feature names introduced by the GEP, if there +# are any. This will allow us to track which feature was introduced by which GEP. +featureNames: + - GatewayReturn421 +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: {} diff --git a/site-src/ko/geps/gep-696/index.md b/site-src/ko/geps/gep-696/index.md new file mode 100644 index 0000000000..bedcc6e658 --- /dev/null +++ b/site-src/ko/geps/gep-696/index.md @@ -0,0 +1,69 @@ +# GEP-696: GEP template + +* Issue: [#696](https://github.com/kubernetes-sigs/gateway-api/issues/696) +* Status: Provisional|Implementable|Experimental|Standard|Deferred|Rejected|Withdrawn|Replaced + +(See [status definitions](../overview.md#gep-states).) + +## TLDR + +(1-2 sentence summary of the proposal) + +## Goals + +(Primary goals of this proposal.) + +## Non-Goals + +(What is out of scope for this proposal.) + +## Introduction + +(Can link to external doc -- but we should bias towards copying +the content into the GEP as online documents are easier to lose +-- e.g. owner messes up the permissions, accidental deletion) + +## API +(... details, can point to PR with changes) + +### Gateway for Ingress (North/South) +(Include API details for North/South use cases) + +### Gateway For Mesh (East/West) +(Include East/West API considerations, examples, and if different - APIs) + +## Conformance Details + +(from https://github.com/kubernetes-sigs/gateway-api/blob/main/geps/gep-2162/index.md#standardize-features-and-conformance-tests-names) + +#### Feature Names + +(Does it require separate feature(s) for mesh? Please add them if necessary) + +Every feature should: + +1. Start with the resource name. i.e HTTPRouteXXX +2. Follow the PascalCase convention. Note that the resource name in the string should come as is and not be converted to PascalCase, i.e HTTPRoutePortRedirect and not HttpRoutePortRedirect. +3. Not exceed 128 characters. +4. Contain only letters and numbers + +### Conformance tests + +Conformance tests file names should try to follow the `pascal-case-name.go` format. +For example for `HTTPRoutePortRedirect` - the test file would be `httproute-port-redirect.go`. + +Treat this guidance as "best effort" because we might have test files that check the combination of several features and can't follow the same format. + +In any case, the conformance tests file names should be meaningful and easy to understand. + +(Make sure to also include conformance tests that cover mesh) + +## Alternatives + +(List other design alternatives and why we did not go in that +direction) + +## References + +(Add any additional document links. Again, we should try to avoid +too much content not in version control to avoid broken links) diff --git a/site-src/ko/geps/gep-696/metadata.yaml b/site-src/ko/geps/gep-696/metadata.yaml new file mode 100644 index 0000000000..0eedd6cabe --- /dev/null +++ b/site-src/ko/geps/gep-696/metadata.yaml @@ -0,0 +1,36 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 696 +name: GEP template +status: Completed +# Any authors who contribute to the GEP in any way should be listed here using +# their GitHub handle. +authors: + - bowei + - robscott + - youngnick + - dprotaso +relationships: + # obsoletes indicates that a GEP makes the linked GEP obsolete, and completely + # replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field + # set back to this GEP, and MUST be moved to Declined. + obsoletes: {} + obsoletedBy: {} + # extends indicates that a GEP extends the linked GEP, adding more detail + # or additional implementation. The extended GEP MUST have its extendedBy + # field set back to this GEP. + extends: {} + extendedBy: {} + # seeAlso indicates other GEPs that are relevant in some way without being + # covered by an existing relationship. + seeAlso: {} +# references is a list of hyperlinks to relevant external references. +# It's intended to be used for storing GitHub discussions, Google docs, etc. +references: {} +# featureNames is a list of the feature names introduced by the GEP, if there +# are any. This will allow us to track which feature was introduced by which GEP. +# This is the value added to supportedFeatures and the conformance tests, in string form. +featureNames: {} +# changelog is a list of hyperlinks to PRs that make changes to the GEP, in +# ascending date order. +changelog: {} diff --git a/site-src/ko/geps/gep-709/709-inline.png b/site-src/ko/geps/gep-709/709-inline.png new file mode 100644 index 0000000000..d46e9ac59f Binary files /dev/null and b/site-src/ko/geps/gep-709/709-inline.png differ diff --git a/site-src/ko/geps/gep-709/709-referencegrant.png b/site-src/ko/geps/gep-709/709-referencegrant.png new file mode 100644 index 0000000000..e211764a8b Binary files /dev/null and b/site-src/ko/geps/gep-709/709-referencegrant.png differ diff --git a/site-src/ko/geps/gep-709/index.md b/site-src/ko/geps/gep-709/index.md new file mode 100644 index 0000000000..1a2ea88f5f --- /dev/null +++ b/site-src/ko/geps/gep-709/index.md @@ -0,0 +1,305 @@ +# GEP-709: Cross Namespace References from Routes + +* Issue: [#709](https://github.com/kubernetes-sigs/gateway-api/issues/709) +* Status: Standard + +!!! note + This resource was originally named "ReferencePolicy". It was renamed + to "ReferenceGrant" to avoid any confusion with policy attachment. + +## TLDR + +This GEP attempts to enable cross namespace forwarding from Routes and provide a +way to simplify adding Route inclusion (Routes including other Routes) in the +future. These are closely related concepts that can be solved with a new +ReferenceGrant resource that enables app admins to describe where they trust +references from. + +## Motivation/User Journeys/Background + +This GEP keeps same namespace references simple while enabling the following +capabilities for cross namespace references: + +1. Retaining full control of Gateway and Routes in an infra namespace, while + targeting apps in different namespaces. +1. Traffic splitting between Services in different namespaces. +1. Mesh overrides to target Services in different namespaces. (For more info, + see GEP [#713](https://github.com/kubernetes-sigs/gateway-api/issues/713)) + +## ReferenceGrant + +Anytime we allow crossing a namespace boundary, we need to be very cautious. +In the past, we've seen that forwarding traffic across namespace boundaries is +a desired feature, but without the kinds of safeguards proposed here, +[vulnerabilities](https://github.com/kubernetes/kubernetes/issues/103675) can +emerge. + +To ensure that Gateway API is able to safely provide this functionality, we need +to enforce a handshake mechanism that requires resources in both namespaces to +agree to this reference. To accomplish that, a new ReferenceGrant resource +should be introduced. + +![Reference Policy](images/709-referencegrant.png) + +With this model, Routes would be able to directly reference Routes and Services +in other namespaces. These references would only be considered valid if a +ReferenceGrant in the target namespace explicitly allowed it. + +The following example shows how a HTTPRoute in namespace foo could reference +a Service in namespace bar. In this example a ReferenceGrant in the bar +namespace explicitly allows references to Services from HTTPRoutes in the foo +namespace. + +```yaml +kind: HTTPRoute +metadata: + name: foo + namespace: foo +spec: + rules: + - matches: + - path: /bar + forwardTo: + backend: + - name: bar + namespace: bar +--- +kind: ReferenceGrant +metadata: + name: bar + namespace: bar +spec: + from: + - group: networking.gateway.k8s.io + kind: HTTPRoute + namespace: foo + to: + - group: core + kind: Service +``` + +### API +This proposed API is fairly straightforward, but comes with a few notable +decisions: + +1. Each ReferenceGrant only supports a single From and To section. Additional + trust relationships can be modeled with additional ReferenceGrant resources. +1. Resource names are intentionally excluded from this policy for simplicity and + because they rarely provide any meaningful protection. A user that is able + to write to resources of a certain kind within a namespace can always rename + resources or change the structure of the resources to match a given policy. +1. A single Namespace is allowed per "From" struct. Although a selector would be + more powerful it may encourage unnecessarily insecure configuration. + +```go +// ReferenceGrant identifies kinds of resources in other namespaces that are +// trusted to reference the specified kinds of resources in the local namespace. +// Each ReferenceGrant can be used to represent a unique trust relationship. +// Additional ReferenceGrants can be used to add to the set of trusted +// sources of inbound references for the namespace they are defined within. +type ReferenceGrant struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of ReferenceGrant. + Spec ReferenceGrantSpec `json:"spec,omitempty"` +} + + +// ReferenceGrantSpec identifies a cross namespace relationship that is trusted +// for Gateway API. +type ReferenceGrantSpec struct { + // From describes the trusted namespaces and kinds that can reference the + // resources described in "To". Each entry in this list must be considered + // to be an additional place that references can be valid from, or to put + // this another way, entries must be combined using OR. + // + // Support: Core + // + // +kubebuilder:validation:MinItems=1 + From []ReferenceGrantFrom `json:"from"` + + // To describes the resources that may be referenced by the resources + // described in "From". Each entry in this list must be considered to be an + // additional place that references can be valid to, or to put this another + // way, entries must be combined using OR. + // + // Support: Core + // + // +kubebuilder:validation:MinItems=1 + To []ReferenceGrantTo `json:"to"` +} + +// ReferenceGrantFrom describes trusted namespaces and kinds. +type ReferenceGrantFrom struct { + // Group is the group of the referent. + // + // Support: Core + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Group string `json:"group"` + + // Kind is the kind of the referent. Although implementations may support + // additional resources, the following Route types are part of the "Core" + // support level for this field: + // + // * HTTPRoute + // * TCPRoute + // * TLSRoute + // * UDPRoute + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Kind string `json:"kind"` + + // Namespace is the namespace of the referent. + // + // Support: Core + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Namespace string `json:"namespace,omitempty"` +} + +// ReferenceGrantTo describes what Kinds are allowed as targets of the +// references. +type ReferenceGrantTo struct { + // Group is the group of the referent. + // + // Support: Core + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Group string `json:"group"` + + // Kind is the kind of the referent. Although implementations may support + // additional resources, the following types are part of the "Core" + // support level for this field: + // + // * Service + // * HTTPRoute + // * TCPRoute + // * TLSRoute + // * UDPRoute + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Kind string `json:"kind"` +} +``` + + +### Benefits + +* Conceptually similar to NetworkPolicy. +* A separate resource enables admins to restrict who can allow cross namespace + references. +* Provides consistent way to control references to any resource from a Route. +* Can be extended in the future for additional use cases. +* A single ReferenceGrant resource can be used for a namespace in place of + separate handshake config on each Service or Route resource. + +#### Exceptions +There are some situations where it MAY be acceptable to ignore ReferenceGrant +in favor of some other security mechanism. This MAY only be done if other +mechanisms like NetworkPolicy can effectively limit cross-namespace references +by the implementation. + +An implementation choosing to make this exception MUST clearly document that +ReferenceGrant is not honored by their implementations and detail which +alternative safeguards are available. Note that this is unlikely to apply to +ingress implementations of the API and will not apply to all mesh +implementations. + +For an example of the risks involved in cross-namespace references, refer to +[CVE-2021-25740](https://github.com/kubernetes/kubernetes/issues/103675). +Implementations of this API need to be very careful to avoid confused deputy +attacks. ReferenceGrant provides a safeguard for that. Exceptions MUST only +be made by implementations that are absolutely certain that other equally +effective safeguards are in place. + +## ForwardTo + +To enable cross-namespace forwarding, we'll need to add an optional `namespace` +field to the ForwardTo BackendRef struct. + +```go +type BackendRef struct { + // ... + + // Namespace is the namespace of the backend. When unspecified, the local + // namespace is inferred. + // + // Support: Core + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +optional + Namespace *string `json:"namespace,omitempty"` +} +``` + +## Alternatives + +### Inline Config +Instead of ReferenceGrant, it is possible to represent these relationships +inline. +![Inline](images/709-inline.png) + +```yaml +kind: HTTPRoute +metadata: + name: foo + namespace: foo +spec: + rules: + - matches: + - path: /bar + forwardTo: + backend: + - name: bar + namespace: bar +--- +kind: Service +metadata: + name: baz + namespace: baz + annotations: + gateway.networking.k8s.io/accept-forwarding-from: bar +``` + +Although this requires less YAML for the simple case, it is less flexible. +Annotations have real limitations and don't provide any room for RBAC +differentiation. Although it's possible that we could eventually add a proper +field to the Service API to represent this, it would be impossible to add this +concept to all potential backend types. + +## Out of scope + +* Although closely related, this GEP does not attempt to improve the + Gateway->Route relationship. That will instead be covered by a future GEP. +* Although this GEP explores how ReferenceGrant could enable Route inclusion, + the details of that feature will be left for a future GEP. + +## References + +**GitHub Issues:** + +* [#411: Clarify how RouteGateways would work if we supported Route->Route + delegation](https://github.com/kubernetes-sigs/gateway-api/issues/411) +* [#582: Allow cross namespace + references](https://github.com/kubernetes-sigs/gateway-api/issues/582) +* [#634: Request Filtering Between Gateways and Namespaced + Routes](https://github.com/kubernetes-sigs/gateway-api/issues/634) + +**Docs:** + +* [Gateway API Reference + Policy](https://docs.google.com/document/d/18MoabVA-fr5XL9cYdf6cxclqRwFpOvHUXV_UYzSiooY/edit) +* [Selection Policy + Proposal](https://docs.google.com/document/d/1S9t4YiDBwe1X7q915zKO0meZ8O_UPa8bzBLWBY8_XdM/edit?usp=sharing) +* [Route Inclusion + Proposal](https://docs.google.com/document/d/1-0mgRRAY784OgGQ1_LCOshpLLbeAtIr4eXd0YVYK4RY/edit#heading=h.8cfxzle5tmqb) +* [Cross Namespace Forwarding + Proposal](https://docs.google.com/document/d/1_B1G9JcNw3skNYLtdK7lTTzOeyz5w2hpa84cKA_MGKk/edit) diff --git a/site-src/ko/geps/gep-709/metadata.yaml b/site-src/ko/geps/gep-709/metadata.yaml new file mode 100644 index 0000000000..3ed29b165e --- /dev/null +++ b/site-src/ko/geps/gep-709/metadata.yaml @@ -0,0 +1,8 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 709 +name: Cross Namespace References from Routes +status: Standard +authors: + - robscott + - youngnick diff --git a/site-src/ko/geps/gep-713/713-ingress-attachment.png b/site-src/ko/geps/gep-713/713-ingress-attachment.png new file mode 100644 index 0000000000..dbd4035aab Binary files /dev/null and b/site-src/ko/geps/gep-713/713-ingress-attachment.png differ diff --git a/site-src/ko/geps/gep-713/713-servicebinding-complex.png b/site-src/ko/geps/gep-713/713-servicebinding-complex.png new file mode 100644 index 0000000000..be4d18cfd3 Binary files /dev/null and b/site-src/ko/geps/gep-713/713-servicebinding-complex.png differ diff --git a/site-src/ko/geps/gep-713/713-servicebinding-simple.png b/site-src/ko/geps/gep-713/713-servicebinding-simple.png new file mode 100644 index 0000000000..b17c69e309 Binary files /dev/null and b/site-src/ko/geps/gep-713/713-servicebinding-simple.png differ diff --git a/site-src/ko/geps/gep-713/713-the-diagram-with-policy-admin.png b/site-src/ko/geps/gep-713/713-the-diagram-with-policy-admin.png new file mode 100644 index 0000000000..181d1d15d7 Binary files /dev/null and b/site-src/ko/geps/gep-713/713-the-diagram-with-policy-admin.png differ diff --git a/site-src/ko/geps/gep-713/index.md b/site-src/ko/geps/gep-713/index.md new file mode 100644 index 0000000000..1038eb06eb --- /dev/null +++ b/site-src/ko/geps/gep-713/index.md @@ -0,0 +1,1162 @@ +# GEP-713: Metaresources and Policy Attachment + +* Issue: [#713](https://github.com/kubernetes-sigs/gateway-api/issues/713) +* Status: Memorandum + +## TLDR + +!!! danger + This GEP is in the process of being updated. + Please see the discussion at https://github.com/kubernetes-sigs/gateway-api/discussions/2927 + and expect further changes, although they will not be as extensive as the + more focussed GEP-2648 and GEP-2649. + Some options under discussion there may make the distinction between Direct + and Inherited Policies moot, which would require a rework. + +This GEP aims to standardize terminology and processes around using one Kubernetes +object to modify the functions of one or more other objects. + +This GEP defines some terms, firstly: _Metaresource_. + +A Kubernetes object that _augments_ the behavior of an object +in a standard way is called a _Metaresource_. + +This document proposes controlling the creation of configuration in the underlying +Gateway data plane using two types of Policy Attachment. +A "Policy Attachment" is a specific type of _metaresource_ that can affect specific +settings across either one object (this is "Direct Policy Attachment"), or objects +in a hierarchy (this is "Inherited Policy Attachment"). + +Individual policy APIs: + +- MUST be their own CRDs (e.g. `TimeoutPolicy`, `RetryPolicy` etc), +- MUST include both `spec` and `status` stanzas +- MUST have the `status` stanza include a `conditions` section using the standard + upstream Condition type +- MAY be included in the Gateway API group and installation or be defined by + implementations +- MUST include a common `TargetRef` struct in their specification to identify + how and where to apply that policy. +- MAY affect more objects than the object specified in the `targetRef`. In this + case, the Policy is an Inherited Policy. A common way to do this is to include + either a `defaults` section, an `overrides` section, or both. +- Policy objects that affect _only_ the object specified in the `targetRef` are + Direct Attached Policies (or more simply, Direct Policies.) + +The biggest difference between the two types of Policy is that Direct Attached +Policies are a strict subset of Policy objects with criteria designed to make +it _much_ easier to understand the state of the system, and so are simpler to +use and can use a more simple `status` design. + +However, Inherited Policies, because of the nature of the useful feature of having +settings cascade across multiple objects in a hierarchy, require knowledge of +more resources, and are consequently harder to understand and require a more +complex status design. + +Splitting these two design patterns apart into separate GEPs is intended to +allow proceeding with stabilizing the simpler (Direct) case while we work on +solving the status problem for the more complex (Inherited) case. + +Direct Attached Policies are further specified in the addendum GEP GEP-2648, +Direct Policy Attachment. + +Inherited Policies are further specified in the addendum GEP-2649, Inherited +Policy Attachment. GEP-2649 also describes a set of expected behaviors +for how settings can flow across a defined hierarchy. + + +## Goals + +* Establish a pattern for Policy resources which will be used for any policies + included in the Gateway API spec +* Establish a pattern for Policy attachment, whether Direct or Inherited, + which must be used for any implementation specific policies used with + Gateway API resources +* Discuss the problems with communicating status for Policy objects, and suggest + mechanisms that Policy APIs can use to mitigate some of them. +* Provide a way to distinguish between required and default values for all + policy API implementations +* Enable policy attachment at all relevant scopes, including Gateways, Routes, + Backends, along with how values should flow across a hierarchy if necessary +* Ensure the policy attachment specification is generic and forward thinking + enough that it could be easily adapted to other grouping mechanisms like + Namespaces in the future +* Provide a means of attachment that works for both ingress and mesh + implementations of this API +* Provide a consistent specification that will ensure familiarity between both + included and implementation-specific policies so they can both be interpreted + the same way. + +## Deferred Goals and Discussions + +* Should Policy objects be able to target more than one object? At the time of + writing, the answer to this is _no_, in the interests of managing complexity + in one change. But this rule can and should be discussed and reexamined in + light of community feedback that users _really_ want this. Any discussion will + need to consider the complexity tradeoffs here. + +## Out of scope + +* Define all potential policies that may be attached to resources +* Design the full structure and configuration of policies + +## Background and concepts + +When designing Gateway API, one of the things we’ve found is that we often need to be +able change the behavior of objects without being able to make changes to the spec +of those objects. Sometimes, this is because we can’t change the spec of the object +to hold the information we need ( ReferenceGrant, from +[GEP-709](../gep-709/index.md), affecting Secrets +and Services is an example, as is Direct Policy Attachment), and sometimes it’s +because we want the behavior change to flow across multiple objects +(this is what Inherited Policy Attachment is for). + +To put this another way, sometimes we need ways to be able to affect how an object +is interpreted in the API, without representing the description of those effects +inside the spec of the object. + +This document describes the ways we design objects to meet these two use cases, +and why you might choose one or the other. + +We use the term “metaresource” to describe the class of objects that _only_ augment +the behavior of another Kubernetes object, regardless of what they are targeting. + +“Meta” here is used in its Greek sense of “more comprehensive” +or “transcending”, and “resource” rather than “object” because “metaresource” +is more pronounceable than “metaobject”. Additionally, a single word is better +than a phrase like “wrapper object” or “wrapper resource” overall, although both +of those terms are effectively synonymous with “metaresource”. + +A "Policy Attachment" is a metaresource that affects the fields in existing objects +(like Gateway or Routes), or influences the configuration that's generated in an +underlying data plane. + +"Direct Policy Attachment" is when a Policy object references a single object _only_, +and only modifies the fields of or the configuration associated with that object. + +"Inherited Policy Attachment" is when a Policy object references a single object +_and any child objects of that object_ (according to some defined hierarchy), and +modifies fields of the child objects, or configuration associated with the child +objects. + +In either case, a Policy may either affect an object by controlling the value +of one of the existing _fields_ in the `spec` of an object, or it may add +additional fields that are _not_ in the `spec` of the object. + +### Why use Policy Attachment at all? + + +Consistent UX across GW implementations + +Support for common tooling such as gwctl that can compute and display effective policies at each layer + +Avoid annotation hell + + +### Direct Policy Attachment + +For more description of the details of Direct Policy Attachment, +see [GEP-2648](../gep-2648/index.md). + +### Inherited Policy Attachment + +For more description of the details of Inherited Policy Attachment, +see [GEP-2649](../gep-2649/index.md). + +### How to determine if a Policy is a Direct or Inherited one + +The basic rule here is "Does the Policy affect _any_ other object aside from +the one it targets?" If not, it's Direct. If so, it's Inherited. + +The reason for this is that Direct Attached Policies make it _much_ easier to +understand the state of the system, and so can use a more simple `status` design. +However, Inherited Policies require knowledge of more resources, and consequently +a more complex status design. + +#### Policy type examples + +The separate GEPs have more examples of policies of each type, but here are two +small examples. Please see the separated GEPs for more examples. + +**BackendTLSPolicy** is the canonical example of a Direct Attached Policy because +it _only_ affects the Service that the Policy attaches to, and affects how that +Service is consumed. But you can know everything you need to about the Service +and BackendTLSPolicy just by looking at those two objects. + +**Hypothetical max body size Policy**: Kate Osborn +[raised this on Slack](https://kubernetes.slack.com/archives/CR0H13KGA/p1708723178714389), +asking if a policy applied to a Gateway configures a data plane setting that +affects routes counts as an Inherited Policy, giving the example of a max body +size Policy. + +In this sort of case, the object does count as an Inherited Policy because +it's affecting not just the properties of the Gateway, but properties of the +Routes attached to it (and you thus need to know about the Policy, the Gateway, +_and_ the Routes to be able to understand the system). + + +## Naming Policy objects + +Although Direct and Inherited Policies behave differently in many respects, in +general they should be named using similar rules. + +Policy objects MUST be clearly named so as to indicate that they are Policy +metaresources. + +The simplest way to do that is to ensure that the type's name contains the `Policy` +string. + +Implementations SHOULD use `Policy` as the last part of the names of object types +that use this pattern. + +If an implementation does not, then they MUST clearly document what objects +are Policy metaresources in their documentation. Again, this is _not recommended_ +without a _very_ good reason. + +### Targeting Virtual Types +In some cases (likely limited to mesh) we may want to apply policies to requests +to external services. To accomplish this, implementations MAY choose to support +a reference to a virtual resource type. For example: + +```yaml +apiVersion: networking.acme.io/v1alpha1 +kind: RetryPolicy +metadata: + name: foo +spec: + default: + maxRetries: 5 + targetRef: + group: networking.acme.io + kind: ExternalService + name: foo.com +``` + +### Conflict Resolution +It is possible for multiple policies to target the same object _and_ the same +fields inside that object. If multiple policy resources target +the same resource _and_ have an identical field specified with different values, +precedence MUST be determined in order of the following criteria, continuing on +ties: + +* Direct Policies override Inherited Policies. If preventing settings from + being overwritten is important, implementations should only use Inherited + Policies, and the `override` stanza that implies. Note also that it's not + intended that Direct and Inherited Policies should overlap, so this should + only come up in exceptional circumstances. +* Inside Inherited Policies, the same setting in `overrides` beats the one in + `defaults`. +* The older Policy based on creation timestamp beats a newer one. For example, +  a Policy with a creation timestamp of "2021-07-15 01:02:03" MUST be given +  precedence over a Policy with a creation timestamp of "2021-07-15 01:02:04". + The goal is to ensure that introducing new, unused policies doesn’t disrupt + existing ones, since changing active rules can cause outages while altering + unused policies poses no risk. +* The Policy appearing first in alphabetical order by `{namespace}/{name}`. For + example, foo/bar is given precedence over foo/baz. + +For a better user experience, a validating webhook can be implemented to prevent +these kinds of conflicts all together. + +## Status and the Discoverability Problem + +So far, this document has talked about what Policy Attachment is, different types +of attachment, and how those attachments work. + +Probably the biggest impediment to this GEP moving forward is the discoverability +problem; that is, it’s critical that an object owner be able to know what policy +is affecting their object, and ideally its contents. + +To understand this a bit better, let’s consider this parable, with thanks to Flynn: + +### The Parable + +It's a sunny Wednesday afternoon, and the lead microservices developer for +Evil Genius Cupcakes is windsurfing. Work has been eating Ana alive for the +past two and a half weeks, but after successfully deploying version 3.6.0 of +the `baker` service this morning, she's escaped early to try to unwind a bit. + +Her shoulders are just starting to unknot when her phone pings with a text +from Chihiro, down in the NOC. Waterproof phones are a blessing, but also a +curse. + +**Chihiro**: _Hey Ana. Things are still running, more or less, but latencies +on everything in the `baker` namespace are crazy high after your last rollout, +and `baker` itself has a weirdly high load. Sorry to interrupt you on the lake +but can you take a look? Thanks!!_ + +Ana stares at the phone for a long moment, heart sinking, then sighs and +turns back to shore. + +What she finds when dries off and grabs her laptop is strange. `baker` does +seem to be taking much more load than its clients are sending, and its clients +report much higher latencies than they’d expect. She doublechecks the +Deployment, the Service, and all the HTTPRoutes around `baker`; everything +looks good. `baker`’s logs show her mostly failed requests... with a lot of +duplicates? Ana checks her HTTPRoute again, though she's pretty sure you +can't configure retries there, and finds nothing. But it definitely looks like +clients are retrying when they shouldn’t be. + +She pings Chihiro. + +**Ana**: _Hey Chihiro. Something weird is up, looks like requests to `baker` +are failing but getting retried??_ + +A minute later they answer. + +**Chihiro**: 🤷 _Did you configure retries?_ + +**Ana**: _Dude. I don’t even know how to._ 😂 + +**Chihiro**: _You just attach a RetryPolicy to your HTTPRoute._ + +**Ana**: _Nope. Definitely didn’t do that._ + +She types `kubectl get retrypolicy -n baker` and gets a permission error. + +**Ana**: _Huh, I actually don’t have permissions for RetryPolicy._ 🤔 + +**Chihiro**: 🤷 _Feels like you should but OK, guess that can’t be it._ + +Minutes pass while both look at logs. + +**Chihiro**: _I’m an idiot. There’s a RetryPolicy for the whole namespace – +sorry, too many policies in the dashboard and I missed it. Deleting that since +you don’t want retries._ + +**Ana**: _Are you sure that’s a good–_ + +Ana’s phone shrills while she’s typing, and she drops it. When she picks it +up again she sees a stack of alerts. She goes pale as she quickly flips +through them: there’s one for every single service in the `baker` namespace. + +**Ana**: _PUT IT BACK!!_ + +**Chihiro**: _Just did. Be glad you couldn't hear all the alarms here._ 😕 + +**Ana**: _What the hell just happened??_ + +**Chihiro**: _At a guess, all the workloads in the `baker` namespace actually +fail a lot, but they seem OK because there are retries across the whole +namespace?_ 🤔 + +Ana's blood runs cold. + +**Chihiro**: _Yeah. Looking a little closer, I think your `baker` rollout this +morning would have failed without those retries._ 😕 + +There is a pause while Ana's mind races through increasingly unpleasant +possibilities. + +**Ana**: _I don't even know where to start here. How long did that +RetryPolicy go in? Is it the only thing like it?_ + +**Chihiro**: _Didn’t look closely before deleting it, but I think it said a few +months ago. And there are lots of different kinds of policy and lots of +individual policies, hang on a minute..._ + +**Chihiro**: _Looks like about 47 for your chunk of the world, a couple hundred +system-wide._ + +**Ana**: 😱 _Can you tell me what they’re doing for each of our services? I +can’t even_ look _at these things._ 😕 + +**Chihiro**: _That's gonna take awhile. Our tooling to show us which policies +bind to a given workload doesn't go the other direction._ + +**Ana**: _...wait. You have to_ build tools _to know if retries are turned on??_ + +Pause. + +**Chihiro**: _Policy attachment is more complex than we’d like, yeah._ 😐 +_Look, how about roll back your `baker` change for now? We can get together in +the morning and start sorting this out._ + +Ana shakes her head and rolls back her edits to the `baker` Deployment, then +sits looking out over the lake as the deployment progresses. + +**Ana**: _Done. Are things happier now?_ + +**Chihiro**: _Looks like, thanks. Reckon you can get back to your sailboard._ 🙂 + +Ana sighs. + +**Ana**: _Wish I could. Wind’s died down, though, and it'll be dark soon. +Just gonna head home._ + +**Chihiro**: _Ouch. Sorry to hear that._ 😐 + +One more look out at the lake. + +**Ana**: _Thanks for the help. Wish we’d found better answers._ 😢 + +### The Problem, restated +What this parable makes clear is that, in the absence of information about what +Policy is affecting an object, it’s very easy to make poor decisions. + +It’s critical that this proposal solve the problem of showing up to three things, +listed in increasing order of desirability: + +- _That_ some Policy is affecting a particular object +- _Which_ Policy is (or Policies are) affecting a particular object +- _What_ settings in the Policy are affecting the object. + +In the parable, if Ana and Chihiro had known that there were Policies affecting +the relevant object, then they could have gone looking for the relevant Policies +and things would have played out differently. If they knew which Policies, they +would need to look less hard, and if they knew what the settings being applied +were, then the parable would have been able to be very short indeed. + +(There’s also another use case to consider, in that Chihiro should have been able +to see that the Policy on the namespace was in use in many places before deleting +it.) + +To put this another way, Policy Attachment is effectively adding a fourth Persona, +the Policy Admin, to Gateway API’s persona list, and without a solution to the +discoverability problem, their actions are largely invisible to the Application +Developer. Not only that, but their concerns cut across the previously established +levels. + +![Gateway API diagram with Policy Admin](images/713-the-diagram-with-policy-admin.png) + + +From the Policy Admin’s point of view, they need to know across their whole remit +(which conceivably could be the whole cluster): + +- _What_ Policy has been created +- _Where_ it’s applied +- _What_ the resultant policy is saying + +Which again, come down to discoverability, and can probably be addressed in similar +ways at an API level to the Application Developer's concerns. + +An important note here is that a key piece of information for Policy Admins and +Cluster Operators is “How many things does this Policy affect?”. In the parable, +this would have enabled Chihiro to know that deleting the Namespace Policy would +affect many other people than just Ana. + +### Problems we need to solve + +Before we can get into solutions, we need to discuss the problems that solutions +may need to solve, so that we have some criteria for evaluating those solutions. + +#### User discoverability + +Let's go through the various users of Gateway API and what they need to know about +Policy Attachment. + +In all of these cases, we should aim to keep the troubleshooting distance low; +that is, that there should be a minimum of hops required between objects from the +one owned by the user to the one responsible for a setting. + +Another way to think of the troubleshooting distance in this context is "How many +`kubectl` commands would the user need to do to understand that a Policy is relevant, +which Policy is relevant, and what configuration the full set of Policy is setting?" + +##### Application Developer Discoverability + +How does Ana, or any Application Developer who owns one or more Route objects know +that their object is affected by Policy, which Policy is affecting it, and what +the content of the Policy is? + +The best outcome is that Ana needs to look only at a specific route to know what +Policy settings are being applied to that Route, and where they come from. +However, some of the other problems below make it very difficult to achieve this. + +##### Policy Admin Discoverability + +How does the Policy Admin know what Policy is applied where, and what the content +of that Policy is? +How do they validate that Policy is being used in ways acceptable to their organization? +For any given Policy object, how do they know how many places it's being used? + +##### Cluster Admin Discoverability + +The Cluster Admin has similar concerns to the Policy Admin, but with a focus on +being able to determine what's relevant when something is broken. + +How does the Cluster Admin know what Policy is applied where, and what the content +of that Policy is? + +For any given Policy object, how do they know how many places it's being used? + +#### Evaluating and Displaying Resultant Policy + +For any given Policy type, whether Direct Attached or Inherited, implementations +will need to be able to _calculate_ the resultant set of Policy to be able to +apply that Policy to the correct parts of their data plane configuration. +However, _displaying_ that resultant set of Policy in a way that is straightforward +for the various personas to consume is much harder. + +The easiest possible option for Application Developers would be for the +implementation to make the full resultant set of Policy available in the status +of objects that the Policy affects. However, this runs into a few problems: + +- The status needs to be namespaced by the implementation +- The status could get large if there are a lot of Policy objects affecting an + object +- Building a common data representation pattern that can fit into a single common + schema is not straightforward. +- Updating one Policy object could cause many affected objects to need to be + updated themselves. This sort of fan-out problem can be very bad for apiserver + load, particularly if Policy changes rapidly, there are a lot of objects, or both. + +##### Status needs to be namespaced by implementation + +Because an object can be affected by multiple implementations at once, any status +we add must be namespaced by the implementation. + +In Route Parent status, we've used the parentRef plus the controller name for this. + +For Policy, we can do something similar and namespace by the reference to the +implementation's controller name. + +We can't easily namespace by the originating Policy because the source could be +more than one Policy object. + +##### Creating common data representation patterns + +The problem here is that we need to have a _common_ pattern for including the +details of an _arbitrarily defined_ object, that needs to be included in the base +API. + +So we can't use structured data, because we have no way of knowing what the +structure will be beforehand. + +This suggests that we need to use unstructured data for representing the main +body of an arbitrary Policy object. + +Practically, this will need to be a string representation of the YAML form of the +body of the Policy object (absent the metadata part of every Kubernetes object). + +Policy Attachment does not mandate anything about the design of the object's top +level except that it must be a Kubernetes object, so the only thing we can rely +on is the presence of the Kubernetes metadata elements: `apiVersion`, `kind`, +and `metadata`. + +A string representation of the rest of the file is the best we can do here. + +##### Fanout status update problems + +The fanout problem is that, when an update takes place in a single object (a +Policy, or an object with a Policy attached), an implementation may need to +update _many_ objects if it needs to place details of what Policy applies, or +what the resultant set of policy is on _every_ object. + +Historically, this is a risky strategy and needs to be carefully applied, as +it's an excellent way to create apiserver load problems, which can produce a large +range of bad effects for cluster stability. + +This does not mean that we can't do anything at all that affects multiple objects, +but that we need to carefully consider what information is stored in status so +that _every_ Policy update does not require a status update. + +#### Solution summary + +Because Policy Attachment is a pattern for APIs, not an API, and needs to address +all the problems above, the strategy this GEP proposes is to define a range of +options for increasing the discoverability of Policy resources, and provide +guidelines for when they should be used. + +It's likely that at some stage, the Gateway API CRDs will include some Policy +resources, and these will be designed with all these discoverabiity solutions +in mind. + + +### Solution cookbook + +This section contains some required patterns for Policy objects and some +suggestions. Each will be marked as MUST, SHOULD, or MAY, using the standard +meanings of those terms. + +Additionally, the status of each solution is noted at the beginning of the section. + +#### Standard label on CRD objects + +Status: Required + +Each CRD that defines a Policy object MUST include a label that specifies that +it is a Policy object, and that label MUST specify the _type_ of Policy attachment +in use. + +The label is `gateway.networking.k8s.io/policy: inherited|direct`. + +This solution is intended to allow both users and tooling to identify which CRDs +in the cluster should be treated as Policy objects, and so is intended to help +with discoverability generally. It will also be used by the forthcoming `kubectl` +plugin. + +##### Design considerations + +This is already part of the API pattern, but is being lifted to more prominence +here. + +#### Standard status struct + +Status: Experimental + +Included in the Direct Policy Attachment GEP. + +Policy objects SHOULD use the upstream `PolicyAncestorStatus` struct in their respective +Status structs. Please see the included `PolicyAncestorStatus` struct, and its use in +the `BackendTLSPolicy` object for detailed examples. Included here is a representative +version. + +This pattern enables different conditions to be set for different "Ancestors" +of the target resource. This is particularly helpful for policies that may be +implemented by multiple controllers or attached to resources with different +capabilities. This pattern also provides a clear view of what resources a +policy is affecting. + +For the best integration with community tooling and consistency across +the broader community, we recommend that all implementations transition +to Policy status with this kind of nested structure. + +This is an `Ancestor` status rather than a `Parent` status, as in the Route status +because for Policy attachment, the relevant object may or may not be the direct +parent. + +For example, `BackendTLSPolicy` directly attaches to a Service, which may be included +in multiple Routes, in multiple Gateways. However, for many implementations, +the status of the `BackendTLSPolicy` will be different only at the Gateway level, +so Gateway is the relevant Ancestor for the status. + +Each Gateway that has a Route that includes a backend with an attached `BackendTLSPolicy` +MUST have a separate `PolicyAncestorStatus` section in the `BackendTLSPolicy`'s +`status.ancestors` stanza, which mandates that entries must be distinct using the +combination of the `AncestorRef` and the `ControllerName` fields as a key. + +See [GEP-1897][gep-1897] for the exact details. + +[gep-1897]: ../gep-1897/index.md + +```go +// PolicyAncestorStatus describes the status of a route with respect to an +// associated Ancestor. +// +// Ancestors refer to objects that are either the Target of a policy or above it in terms +// of object hierarchy. For example, if a policy targets a Service, an Ancestor could be +// a Route or a Gateway. + +// In the context of policy attachment, the Ancestor is used to distinguish which +// resource results in a distinct application of this policy. For example, if a policy +// targets a Service, it may have a distinct result per attached Gateway. +// +// Policies targeting the same resource may have different effects depending on the +// ancestors of those resources. For example, different Gateways targeting the same +// Service may have different capabilities, especially if they have different underlying +// implementations. +// +// For example, in BackendTLSPolicy, the Policy attaches to a Service that is +// used as a backend in a HTTPRoute that is itself attached to a Gateway. +// In this case, the relevant object for status is the Gateway, and that is the +// ancestor object referred to in this status. +// +// Note that a Target of a Policy is also a valid Ancestor, so for objects where +// the Target is the relevant object for status, this struct SHOULD still be used. +type PolicyAncestorStatus struct { + // AncestorRef corresponds with a ParentRef in the spec that this + // RouteParentStatus struct describes the status of. + AncestorRef ParentReference `json:"ancestorRef"` + + // ControllerName is a domain/path string that indicates the name of the + // controller that wrote this status. This corresponds with the + // controllerName field on GatewayClass. + // + // Example: "example.net/gateway-controller". + // + // The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + // valid Kubernetes names + // (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + // + // Controllers MUST populate this field when writing status. Controllers should ensure that + // entries to status populated with their ControllerName are cleaned up when they are no + // longer necessary. + ControllerName GatewayController `json:"controllerName"` + + // Conditions describes the status of the Policy with respect to the given Ancestor. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + + +// PolicyStatus defines the common attributes that all Policies SHOULD include +// within their status. +type PolicyStatus struct { + // Ancestors is a list of ancestor resources (usually Gateways) that are + // associated with the route, and the status of the route with respect to + // each ancestor. When this route attaches to a parent, the controller that + // manages the parent and the ancestors MUST add an entry to this list when + // the controller first sees the route and SHOULD update the entry as + // appropriate when the relevant ancestor is modified. + // + // Note that choosing the relevant ancestor is left to the Policy designers; + // an important part of Policy design is designing the right object level at + // which to namespace this status. + // + // Note also that implementations MUST ONLY populate ancestor status for + // the Ancestor resources they are responsible for. Implementations MUST + // use the ControllerName field to uniquely identify the entries in this list + // that they are responsible for. + // + // A maximum of 32 ancestors will be represented in this list. An empty list + // means the Policy is not relevant for any ancestors. + // + // +kubebuilder:validation:MaxItems=32 + Ancestors []PolicyAncestorStatus `json:"ancestors"` +} +``` + +##### Design considerations + +This is recommended as the base for Policy object's status. As Policy Attachment +is a pattern, not an API, "recommended" is the strongest we can make this, but +we believe that standardizing this will help a lot with discoverability. + +Note that is likely that all Gateway API tooling will expect policy status to follow +this structure. To benefit from broader consistency and discoverability, we +recommend transitioning to this structure for all Gateway API Policies. + +#### Standard status Condition on Policy-affected objects + +Support: Provisional + +This solution is IN PROGRESS and so is not binding yet. + +However, a version of this proposal is now included in the Direct Policy +Attachment GEP. + +This solution requires definition in a GEP of its own to become binding. +[GEP-2923](https://github.com/kubernetes-sigs/gateway-api/issues/2923) has been +opened to cover some aspects of this work. + +**The description included here is intended to illustrate the sort of solution +that an eventual GEP will need to provide, _not to be a binding design.** + +Implementations that use Policy objects MUST put a Condition into `status.Conditions` +of any objects affected by a Policy. + +That Condition MUST have a `type` ending in `PolicyAffected` (like +`gateway.networking.k8s.io/PolicyAffected`), +and have the optional `observedGeneration` field kept up to date when the `spec` +of the Policy-attached object changes. + +Implementations SHOULD use their own unique domain prefix for this Condition +`type` - it is recommended that implementations use the same domain as in the +`controllerName` field on GatewayClass (or some other implementation-unique +domain for implementations that do not use GatewayClass).) + +For objects that do _not_ have a `status.Conditions` field available (`Secret` +is a good example), that object MUST instead have an annotation of +`gateway.networking.k8s.io/PolicyAffected: true` (or with an +implementation-specific domain prefix) added instead. + + +##### Design Considerations +The intent here is to add at least a breadcrumb that leads object owners to have +some way to know that their object is being affected by another object, while +minimizing the number of updates necessary. + +Minimizing the object updates is done by only having an update be necessary when +the affected object starts or stops being affected by a Policy, rather than if +the Policy itself has been updated. + +There is already a similar Condition to be placed on _Policy_ objects, rather +than on the _targeted_ objects, so this solution is also being included in the +Conditions section below. + +#### GatewayClass status Extension Types listing + +Support: Provisional + +This solution is IN PROGRESS, and so is not binding yet. + +Each implementation MUST list all relevant CRDs in its GatewayClass status (like +Policy, and other extension types, like paramsRef targets, filters, and so on). + +This is going to be tracked in its own GEP, https://github.com/kubernetes-sigs/gateway-api/discussions/2118 +is the initial discussion. This document will be updated with the details once +that GEP is opened. + +##### Design Considerations + +This solution: + +- is low cost in terms of apiserver updates (because it's only on the GatewayClass, + and only on implementation startup) +- provides a standard place for all users to look for relevant objects +- ties into the Conformance Profiles design and other efforts about GatewayClass + status + +#### Standard status stanza + +Support: Provisional + +This solution is IN PROGRESS and so is not binding yet. + +This solution requires definition in a GEP of its own to become binding. + +**The description included here is intended to illustrate the sort of solution +that an eventual GEP will need to provide, _not to be a binding design. THIS IS +AN EXPERIMENTAL SOLUTION DO NOT USE THIS YET.** + +An implementation SHOULD include the name, namespace, apiGroup and Kind of Policies +affecting an object in the new `effectivePolicy` status stanza on Gateway API +objects. + +This stanza looks like this: +```yaml +kind: Gateway +... +status: + effectivePolicy: + - name: some-policy + namespace: some-namespace + apiGroup: implementation.io + kind: AwesomePolicy + ... +``` + +##### Design Considerations + +This solution is designed to limit the number of status updates required by an +implementation to when a Policy starts or stops being relevant for an object, +rather than if that Policy's settings are updated. + +It helps a lot with discoverability, but comes at the cost of a reasonably high +fanout cost. Implementations using this solution SHOULD ensure that status updates +are deduplicated and only sent to the apiserver when absolutely necessary. + +Ideally, these status updates SHOULD be in a separate, lower-priority queue than +other status updates or similar solution. + +#### PolicyBinding resource + +Support: Provisional + +This solution is IN PROGRESS and so is not binding yet. + +This solution requires definition in a GEP of its own to become binding. + +**The description included here is intended to illustrate the sort of solution +that the eventual GEP will need to provide, _not to be a binding design. THIS IS +AN EXPERIMENTAL SOLUTION DO NOT USE THIS YET.** + +Implementations SHOULD create an instance of a new `gateway.networking.k8s.io/EffectivePolicy` +object when one or more Policy objects become relevant to the target object. + +The `EffectivePolicy` object MUST be in the same namespace as the object targeted +by the Policy, and must have the _same name_ as the object targeted like the Policy. +This is intended to mirror the Services/Endpoints naming convention, to allow for +ease of discovery. + +The `EffectivePolicy` object MUST set the following information: + +- The name, namespace, apiGroup and Kind of Policy objects affecting the targeted + object. +- The full resultant set of Policy affecting the targeted object. + +The above details MUST be namespaced using the `controllerName` of the implementation +(could also be by GatewayClass), similar to Route status being namespaced by +`parentRef`. + +An example `EffectivePolicy` object is included here - this may be superseded by +a later GEP and should be updated or removed in that case. Note that it does +_not_ contain a `spec` and a `status` stanza - by definition this object _only_ +contains `status` information. + +```yaml +kind: EffectivePolicy +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: targeted-object + namespace: targeted-object-namespace +policies: +- controllerName: implementation.io/ControllerName + objects: + - name: some-policy + namespace: some-namespace + apiGroup: implementation.io + kind: AwesomePolicy + resultantPolicy: + awesomePolicy: + configitem1: + defaults: + foo: 1 + overrides: + bar: important-setting + +``` + +Note here that the `resultantPolicy` setting is defined using the same mechanisms +as an `unstructured.Unstructured` object in the Kubernetes Go libraries - it's +effectively a `map[string]struct{}` that is stored as a `map[string]string` - +which allows an arbitrary object to be specified there. + +Users or tools reading the config underneath `resultantPolicy` SHOULD display +it in its encoded form, and not try to deserialize it in any way. + +The rendered YAML MUST be usable as the `spec` for the type given. + +##### Design considerations + +This will provide _full_ visibility to end users of the _actual settings_ being +applied to their object, which is a big discoverability win. + +However, it relies on the establishment and communication of a convention ("An +EffectivePolicy is right next to your affected object"), that may not be desirable. + +Thus its status as EXPERIMENTAL DO NOT USE YET. + +#### Validating Admission Controller to inform users about relevant Policy + +Implementations MAY supply a Validating Admission Webhook that will return a +WARNING message when an applied object is affected by some Policy. + +The warning message MAY include the name, namespace, apiGroup and Kind of relevant +Policy objects. + +##### Design Considerations + +Pro: + +- This gives object owners a very clear signal that something some Policy is + going to affect their object, at apply time, which helps a lot with discoverability. + +Cons: + +- Implementations would have to have a webhook, which is another thing to run. +- The webhook will need to have the same data model that the implementation uses, + and keep track of which GatewayClasses, Gateways, Routes, and Policies are + relevant. Experience suggests this will not be a trivial engineering exercise,and will add a lot of implementation complexity. + +#### `kubectl` plugin or command-line tool +To help improve UX and standardization, a kubectl plugin will be developed that +will be capable of describing the computed sum of policy that applies to a given +resource, including policies applied to parent resources. + +Each Policy CRD that wants to be supported by this plugin will need to follow +the API structure defined above and add the [corresponding label](index.md#standard-label-on-crd-objects) +to the CRD. + +### Conditions + +Implementations using Policy objects MUST include a `spec` and `status` stanza, +and the `status` stanza MUST contain a `conditions` stanza, using the standard +Condition format. + +Policy authors should consider namespacing the `conditions` stanza with a +`controllerName`, as in Route status, if more than one implementation will be +reconciling the Policy type. + +#### On `Policy` objects + +Controllers using the Gateway API policy attachment model MUST populate the +`Accepted` condition and reasons as defined below on policy resources to provide +a consistent experience across implementations. + +```go +// PolicyConditionType is a type of condition for a policy. +type PolicyConditionType string + +// PolicyConditionReason is a reason for a policy condition. +type PolicyConditionReason string + +const ( + // PolicyConditionAccepted indicates whether the policy has been accepted or rejected + // by a targeted resource, and why. + // + // Possible reasons for this condition to be True are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "Conflicted" + // * "Invalid" + // * "TargetNotFound" + // + PolicyConditionAccepted PolicyConditionType = "Accepted" + + // PolicyReasonAccepted is used with the "Accepted" condition when the policy has been + // accepted by the targeted resource. + PolicyReasonAccepted PolicyConditionReason = "Accepted" + + // PolicyReasonConflicted is used with the "Accepted" condition when the policy has not + // been accepted by a targeted resource because there is another policy that targets the same + // resource and a merge is not possible. + PolicyReasonConflicted PolicyConditionReason = "Conflicted" + + // PolicyReasonInvalid is used with the "Accepted" condition when the policy is syntactically + // or semantically invalid. + PolicyReasonInvalid PolicyConditionReason = "Invalid" + + // PolicyReasonTargetNotFound is used with the "Accepted" condition when the policy is attached to + // an invalid target resource + PolicyReasonTargetNotFound PolicyConditionReason = "TargetNotFound" +) +``` + +#### On targeted resources + +(copied from [Standard status Condition on Policy-affected objects](#standard-status-condition-on-policy-affected-objects)) + +This solution requires definition in a GEP of its own to become binding. + +**The description included here is intended to illustrate the sort of solution +that an eventual GEP will need to provide, _not to be a binding design.** + +Implementations that use Policy objects MUST put a Condition into `status.Conditions` +of any objects affected by a Policy. + +That Condition must have a `type` ending in `PolicyAffected` (like +`gateway.networking.k8s.io/PolicyAffected`), +and have the optional `observedGeneration` field kept up to date when the `spec` +of the Policy-attached object changes. + +Implementations _should_ use their own unique domain prefix for this Condition +`type` - it is recommended that implementations use the same domain as in the +`controllerName` field on GatewayClass (or some other implementation-unique +domain for implementations that do not use GatewayClass).) + +For objects that do _not_ have a `status.Conditions` field available (`Secret` +is a good example), that object MUST instead have an annotation of +`gateway.networking.k8s.io/PolicyAffected: true` (or with an +implementation-specific domain prefix) added instead. + +### Interaction with Custom Filters and other extension points +There are multiple methods of custom extension in the Gateway API. Policy +attachment and custom Route filters are two of these. Policy attachment is +designed to provide arbitrary configuration fields that decorate Gateway API +resources. Route filters provide custom request/response filters embedded inside +Route resources. Both are extension methods for fields that cannot easily be +standardized as core or extended fields of the Gateway API. The following +guidance should be considered when introducing a custom field into any Gateway +controller implementation: + +1. For any given field that a Gateway controller implementation needs, the + possibility of using core or extended should always be considered before + using custom policy resources. This is encouraged to promote standardization + and, over time, to absorb capabilities into the API as first class fields, + which offer a more streamlined UX than custom policy attachment. + +2. Although it's possible that arbitrary fields could be supported by custom + policy, custom route filters, and core/extended fields concurrently, it is + recommended that implementations only use multiple mechanisms for + representing the same fields when those fields really _need_ the defaulting + and/or overriding behavior that Policy Attachment provides. For example, a + custom filter that allowed the configuration of Authentication inside a + HTTPRoute object might also have an associated Policy resource that allowed + the filter's settings to be defaulted or overridden. It should be noted that + doing this in the absence of a solution to the status problem is likely to + be *very* difficult to troubleshoot. + +## Removing BackendPolicy +BackendPolicy represented the initial attempt to cover policy attachment for +Gateway API. Although this proposal ended up with a similar structure to +BackendPolicy, it is not clear that we ever found sufficient value or use cases +for BackendPolicy. Given that this proposal provides more powerful ways to +attach policy, BackendPolicy was removed. + +## Alternatives considered + +### 1. ServiceBinding for attaching Policies and Routes for Mesh +A new ServiceBinding resource has been proposed for mesh use cases. This would +provide a way to attach policies, including Routes to a Service. + +Most notably, these provide a way to attach different policies to requests +coming from namespaces or specific Gateways. In the example below, a +ServiceBinding in the consumer namespace would be applied to the selected +Gateway and affect all requests from that Gateway to the foo Service. Beyond +policy attachment, this would also support attaching Routes as policies, in this +case the attached HTTPRoute would split requests between the foo-a and foo-b +Service instead of the foo Service. + +![Simple Service Binding Example](images/713-servicebinding-simple.png) + +This approach can be used to attach a default set of policies to all requests +coming from a namespace. The example below shows a ServiceBinding defined in the +producer namespace that would apply to all requests from within the same +namespace or from other namespaces that did not have their own ServiceBindings +defined. + +![Complex Service Binding Example](images/713-servicebinding-complex.png) + +#### Advantages +* Works well for mesh and any use cases where requests don’t always transit + through Gateways and Routes. +* Allows policies to apply to an entire namespace. +* Provides very clear attachment of polices, routes, and more to a specific + Service. +* Works well for ‘shrink-wrap application developers’ - the packaged app does + not need to know about hostnames or policies or have extensive templates. +* Works well for ‘dynamic’ / programmatic creation of workloads ( Pods,etc - see + CertManager) +* It is easy to understand what policy applies to a workload - by listing the + bindings in the namespace. + +#### Disadvantages +* Unclear how this would work with an ingress model. If Gateways, Routes, and + Backends are all in different namespaces, and each of those namespaces has + different ServiceBindings applying different sets of policies, it’s difficult + to understand which policy would be applied. +* Unclear if/how this would interact with existing the ingress focused policy + proposal described below. If both coexisted, would it be possible for a user + to understand which policies were being applied to their requests? +* Route status could get confusing when Routes were referenced as a policy by + ServiceBinding +* Introduces a new mesh specific resource. + +### 2. Attaching Policies for Ingress +An earlier proposal for policy attachment in the Gateway API suggested adding +policy references to each Resource. This works very naturally for Ingress use +cases where all requests follow a path through Gateways, Routes, and Backends. +Adding policy attachment at each level enables different roles to define +defaults and allow overrides at different levels. + +![Simple Ingress Attachment Example](images/713-ingress-attachment.png) + +#### Advantages +* Consistent policy attachment at each level +* Clear which policies apply to each component +* Naturally translates to hierarchical Ingress model with ability to delegate + policy decisions to different roles + +#### Disadvantages +* Policy overrides could become complicated +* At least initially, policy attachment on Service would have to rely on Service + annotations or references from policy to Service(s) +* No way to attach policy to other resources such as namespace or ServiceImport +* May be difficult to modify Routes and Services if other components/roles are + managing them (eg Knative) + +### 3. Shared Policy Resource +This is really just a slight variation or extension of the main proposal in this +GEP. We would introduce a shared policy resource. This resource would follow the +guidelines described above, including the `targetRef` as defined as well as +`default` and `override` fields. Instead of carefully crafted CRD schemas for +each of the `default` and `override` fields, we would use more generic +`map[string]string` values. This would allow similar flexibility to annotations +while still enabling the default and override concepts that are key to this +proposal. + +Unfortunately this would be difficult to validate and would come with many of +the downsides of annotations. A validating webhook would be required for any +validation which could result in just as much or more work to maintain than +CRDs. At this point we believe that the best experience will be from +implementations providing their own policy CRDs that follow the patterns +described in this GEP. We may want to explore tooling or guidance to simplify +the creation of these policy CRDs to help simplify implementation and extension +of this API. + +## References + +**Issues** +* [Extensible Service Policy and Configuration](https://github.com/kubernetes-sigs/gateway-api/issues/611) + +**Docs** +* [Policy Attachment and Binding](https://docs.google.com/document/d/13fyptUtO9NV_ZAgkoJlfukcBf2PVGhsKWG37yLkppJo/edit?resourcekey=0-Urhtj9gBkGBkSL1gHgbWKw) diff --git a/site-src/ko/geps/gep-713/metadata.yaml b/site-src/ko/geps/gep-713/metadata.yaml new file mode 100644 index 0000000000..afd8c9b75e --- /dev/null +++ b/site-src/ko/geps/gep-713/metadata.yaml @@ -0,0 +1,32 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 713 +name: Metaresources and Policy Attachment +status: Memorandum +authors: + - youngnick + - robscott + - kflynn + - sanjaypujare + - spacewander +relationships: + extendedBy: + - name: Direct Policy Attachment + number: 2648 + description: Split out Direct Policy Attachment + - name: Inherited Policy Attachment + number: 2649 + description: Split out Inherited Policy Attachment +references: + - "https://github.com/kubernetes-sigs/gateway-api/issues/611" + - "https://docs.google.com/document/d/13fyptUtO9NV_ZAgkoJlfukcBf2PVGhsKWG37yLkppJo/edit?resourcekey=0-Urhtj9gBkGBkSL1gHgbWKw" + - "https://github.com/kubernetes-sigs/gateway-api/discussions/2927" +changelog: + - "https://github.com/kubernetes-sigs/gateway-api/pull/715" + - "https://github.com/kubernetes-sigs/gateway-api/pull/1565" + - "https://github.com/kubernetes-sigs/gateway-api/pull/2128" + - "https://github.com/kubernetes-sigs/gateway-api/pull/2283" + - "https://github.com/kubernetes-sigs/gateway-api/pull/2448" + - "https://github.com/kubernetes-sigs/gateway-api/pull/2654" + - "https://github.com/kubernetes-sigs/gateway-api/pull/2660" + - "https://github.com/kubernetes-sigs/gateway-api/pull/2813" diff --git a/site-src/ko/geps/gep-718/index.md b/site-src/ko/geps/gep-718/index.md new file mode 100644 index 0000000000..8a78740be8 --- /dev/null +++ b/site-src/ko/geps/gep-718/index.md @@ -0,0 +1,337 @@ +# GEP-718: Rework forwardTo segment in routes + +* Issue: [#718](https://github.com/kubernetes-sigs/gateway-api/issues/718) +* Status: Standard + +## Motivation + +### Complications due to the `serviceName` shortcut + +Within `RouteForwardTo` (and `HTTPRouteForwardTo` by extension) there exists +two mechanisms to specify the upstream network endpoint where the traffic should +be forwarded to: +- `ServiceName`: the name of the Kubernetes Service +- `BackendRef`: a LocalObjectReference to a resource, this is an extension point in the API + +While working on [#685](https://github.com/kubernetes-sigs/gateway-api/pull/685), +it came to light that: +1. `BackendRef` itself could be used to point to a Kubernetes Service +2. With [GEP-709](https://github.com/kubernetes-sigs/gateway-api/pull/711), +there will be a need to introduce a new `namespace` field which will enable use-cases to forward +traffic to a services and backends located in different namespaces + +While (1) can be fixed with more validation and documentation, it only solves for +the specific case. (2) requires adding two fields: `serviceNamespace` +and `BackendRef.Namespace` - something we would like to avoid since the `serviceName` +field was introduced only as a shortcut and adding more service-specific fields +defeats the original purpose. + +These problems are in addition to the original problem that +[#685](https://github.com/kubernetes-sigs/gateway-api/pull/685) attempts to solve: +clarifying port requirements when a port is required or not. +We have been updating documentation to tackle such corner-cases but that +continues to result in more and more elaborations. Some excerpts from our +existing documentation: +``` + // ServiceName refers to the name of the Service to mirror matched requests + // to. When specified, this takes the place of BackendRef. If both + // BackendRef and ServiceName are specified, ServiceName will be given + // precedence. + + // BackendRef is a local object reference to mirror matched requests to. If + // both BackendRef and ServiceName are specified, ServiceName will be given + // precedence. + + // Weight specifies the proportion of HTTP requests forwarded to the backend + // referenced by the ServiceName or BackendRef field. This is computed as + + // Port specifies the destination port number to use for the + // backend referenced by the ServiceName or BackendRef field. + // If unspecified, the destination port in the request is used + // when forwarding to a backendRef or serviceName. +``` + +### Simplifying `RouteForwardTo` + +RouteForwardTo is not the best of the names. Using a noun instead of a verb +would help with in-person communication and documentation. +Since we are already considering dropping the special case of `service` as a +backend, we have an opportunity to further simplify `RouteForwardTo` for better +UX. + +## Proposal + +- Remove the `ServiceName` field from `RouteForwardTo` +- Introduce `Service` as a default for `BackendRef.Kind` +- Pull fields from `RouteForwardTo.BackendRef` into `RouteForwardTo` itself +- Rename `RouteForwardTo` to `BackendRef` +- Rename `Route.Spec.Rules[].ForwardTo[]` to `Route.Spec.Rules[].BackendRefs[]` in + all routes +- Apply the same to HTTP types and filters + +## API + +The updated `BackendRef` (formerly `RouteForwardTo`) struct will be: +(HTTP version has been omitted for brevity) + +```go +// BackendRef defines how and where a request should be forwarded from the Gateway. +type BackendRef struct { + // Group is the group of the backend resource. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Group string `json:"group"` + + // Kind is kind of the backend resource. + // + // Support: Core (Kubernetes Service) + // Support: Implementation-specific (any other resource) + // + // +optional + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:default="service" + Kind *string `json:"kind"` + + // Name is the name of the backend resource to forward matched requests to. + // + // If the referent cannot be found, the rule is not included in the route. + // The controller should raise the "ResolvedRefs" condition on the Gateway + // with the "DegradedRoutes" reason. The gateway status for this route should + // be updated with a condition that describes the error more specifically. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Name string `json:"name"` + + // Port specifies the destination port number to use for the + // backend resource. + // This field is required when the backend is a Kubernetes Service. + // + // Support: Core + // + // +optional + Port *PortNumber `json:"port,omitempty"` + + // Weight specifies the proportion of HTTP requests forwarded to the backend + // This is computed as weight/(sum of all weights in this Backends list). + // For non-zero values, there may be some epsilon from the exact proportion + // defined here depending on the precision an implementation supports. Weight + // is not a percentage and the sum of weights does not need to equal 100. + // + // If only one backend is specified and it has a weight greater than 0, 100% + // of the traffic is forwarded to that backend. If weight is set to 0, no + // traffic should be forwarded for this entry. If unspecified, weight + // defaults to 1. + // + // Support: Extended + // + // +optional + // +kubebuilder:default=1 + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=1000000 + Weight *int32 `json:"weight,omitempty"` +} +``` + +A summarized diff for the changes being proposed: + +```patch +diff --git a/apis/v1alpha1/shared_types.go b/apis/v1alpha1/shared_types.go +index 458145f..de720cd 100644 +--- a/apis/v1alpha1/shared_types.go ++++ b/apis/v1alpha1/shared_types.go +@@ -94,51 +94,39 @@ type GatewayReference struct { + Namespace string `json:"namespace"` + } + +-// RouteForwardTo defines how a Route should forward a request. +-type RouteForwardTo struct { +- // ServiceName refers to the name of the Service to forward matched requests +- // to. When specified, this takes the place of BackendRef. If both +- // BackendRef and ServiceName are specified, ServiceName will be given +- // precedence. ++// BackendRef defines how and where a request should be forwarded from the Gateway. ++type BackendRef struct { ++ // Name is the name of the backend resource to forward matched requests to. + // + // If the referent cannot be found, the rule is not included in the route. + // The controller should raise the "ResolvedRefs" condition on the Gateway + // with the "DegradedRoutes" reason. The gateway status for this route should + // be updated with a condition that describes the error more specifically. + // +- // The protocol to use is defined using AppProtocol field (introduced in +- // Kubernetes 1.18) in the Service resource. In the absence of the +- // AppProtocol field a `networking.x-k8s.io/app-protocol` annotation on the +- // BackendPolicy resource may be used to define the protocol. If the +- // AppProtocol field is available, this annotation should not be used. The +- // AppProtocol field, when populated, takes precedence over the annotation +- // in the BackendPolicy resource. For custom backends, it is encouraged to +- // add a semantically-equivalent field in the Custom Resource Definition. ++ // +kubebuilder:validation:MinLength=1 ++ // +kubebuilder:validation:MaxLength=253 ++ Name string `json:"name"` ++ ++ // Kind is kind of the backend resource. + // +- // Support: Core ++ // Support: Core (Kubernetes Service) ++ // Support: Custom (any other resource) + // + // +optional ++ // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 +- ServiceName *string `json:"serviceName,omitempty"` ++ // +kubebuilder:default="service" ++ Kind *string `json:"kind"` + +- // BackendRef is a reference to a backend to forward matched requests to. If +- // both BackendRef and ServiceName are specified, ServiceName will be given +- // precedence. +- // +- // If the referent cannot be found, the rule is not included in the route. +- // The controller should raise the "ResolvedRefs" condition on the Gateway +- // with the "DegradedRoutes" reason. The gateway status for this route should +- // be updated with a condition that describes the error more specifically. ++ // Group is the group of the backend resource. + // +- // Support: Custom +- // +- // +optional +- BackendRef *LocalObjectReference `json:"backendRef,omitempty"` ++ // +kubebuilder:validation:MinLength=1 ++ // +kubebuilder:validation:MaxLength=253 ++ Group string `json:"group"` + + // Port specifies the destination port number to use for the +- // backend referenced by the ServiceName or BackendRef field. +- // If unspecified, the destination port in the request is used +- // when forwarding to a backendRef or serviceName. ++ // backend resource. ++ // This field is required when the backend is a Kubernetes Service. + // + // Support: Core + // +@@ -146,11 +134,10 @@ type RouteForwardTo struct { + Port *PortNumber `json:"port,omitempty"` + + // Weight specifies the proportion of HTTP requests forwarded to the backend +- // referenced by the ServiceName or BackendRef field. This is computed as +- // weight/(sum of all weights in this ForwardTo list). For non-zero values, +- // there may be some epsilon from the exact proportion defined here +- // depending on the precision an implementation supports. Weight is not a +- // percentage and the sum of weights does not need to equal 100. ++ // This is computed as weight/(sum of all weights in this Backends list). ++ // For non-zero values, there may be some epsilon from the exact proportion ++ // defined here depending on the precision an implementation supports. Weight ++ // is not a percentage and the sum of weights does not need to equal 100. + // + // If only one backend is specified and it has a weight greater than 0, 100% + // of the traffic is forwarded to that backend. If weight is set to 0, no +``` + +## Examples + + +For Kubernetes Services, an updated `forwardTo` section will read as follows: + +```yaml +... +backendRefs: +- name: foo-service-v1 + port: 80 + weight: 80 +- name: foo-service-canary + port: 80 + weight: 20 +... +``` + +Here, the `kind` field is omitted as it will be injected as a default. + +For custom backends, the API will look like the following: + +```yaml +... +backendRefs: +- name: foo-v1 + kind: server + group: networking.acme.io + port: 80 + weight: 80 +- name: foo-v1-canary + kind: server + group: networking.acme.io + port: 80 + weight: 20 +... +``` + +For completeness, here is an example of HTTPRoute: + +```yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: HTTPRoute +metadata: + name: bar-route + labels: + gateway: prod-web-gw +spec: + hostnames: + - "bar.example.com" + rules: + - matches: + - headers: + type: Exact + values: + env: canary + backendRefs: + - name: foo-service-v1 + port: 80 + weight: 80 + - name: foo-service-canary + port: 80 + weight: 20 +``` + +## Alternatives considered + +### Rename serviceName to backendName + +As suggested in [this comment](https://github.com/kubernetes-sigs/gateway-api/pull/685#discussion_r667285837), +we could buy the best of both the worlds by introducing `backendName`: + +```yaml +forwardTo: +- backendName: foo + port: 80 + kind: +``` + +While this saves one line of YAML (`backendRef:`), it could be potentially +violating the `Naming of the reference field` +[API convention][api-conventions]. +Most of our object references are of the form `XRef`. + +## Concerns resolved + +A concern was raised around flattening of object reference fields i.e. including +port and weight field alongside object reference is by k8s API conventions or not. +This is not a problem and has been confirmed with API maintainers +([comment](https://github.com/kubernetes-sigs/gateway-api/pull/719#discussion_r678555744)). + +## Out of scope + +N/A + +## References + +Existing documentation: +- [RouteForwardTo](https://github.com/kubernetes-sigs/gateway-api/blob/a9d45b51c396fbed022204af0185b00a4ac7e282/apis/v1alpha2/shared_types.go#L97-L167) +- [HTTPRouteForwardTo](https://github.com/kubernetes-sigs/gateway-api/blob/a9d45b51c396fbed022204af0185b00a4ac7e282/apis/v1alpha2/httproute_types.go#L731-L813) +- [#685](https://github.com/kubernetes-sigs/gateway-api/pull/685) + - [Comment thread that spawned this GEP](https://github.com/kubernetes-sigs/gateway-api/pull/685#discussion_r640204333) +- [#578](https://github.com/kubernetes-sigs/gateway-api/issues/578) + +[api-conventions]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#naming-of-the-reference-field diff --git a/site-src/ko/geps/gep-718/metadata.yaml b/site-src/ko/geps/gep-718/metadata.yaml new file mode 100644 index 0000000000..4d435a8862 --- /dev/null +++ b/site-src/ko/geps/gep-718/metadata.yaml @@ -0,0 +1,8 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 718 +name: Rework forwardTo segment in routes +status: Standard +authors: + - hbagdi + - robscott diff --git a/site-src/ko/geps/gep-724/724-alt1.png b/site-src/ko/geps/gep-724/724-alt1.png new file mode 100644 index 0000000000..6c2c44ea7d Binary files /dev/null and b/site-src/ko/geps/gep-724/724-alt1.png differ diff --git a/site-src/ko/geps/gep-724/724-alt2.png b/site-src/ko/geps/gep-724/724-alt2.png new file mode 100644 index 0000000000..3e83f5d79d Binary files /dev/null and b/site-src/ko/geps/gep-724/724-alt2.png differ diff --git a/site-src/ko/geps/gep-724/724-proposal.png b/site-src/ko/geps/gep-724/724-proposal.png new file mode 100644 index 0000000000..c2d315154d Binary files /dev/null and b/site-src/ko/geps/gep-724/724-proposal.png differ diff --git a/site-src/ko/geps/gep-724/index.md b/site-src/ko/geps/gep-724/index.md new file mode 100644 index 0000000000..59bab7d258 --- /dev/null +++ b/site-src/ko/geps/gep-724/index.md @@ -0,0 +1,699 @@ +# GEP-724: Refresh Route-Gateway Binding + +* Issue: [#724](https://github.com/kubernetes-sigs/gateway-api/issues/724) +* Status: Standard + +## TLDR + +This GEP proposes changes to Route-Gateway binding that will result in Routes +attaching to Gateways with direct references. When supporting Routes in multiple +namespaces, Gateways will need to specify the namespaces they trust Routes in. +These changes will slightly simplify the Route-Gateway relationship and make way +for the future addition of Route inclusion (Routes including other Routes). + +## Goals + +Refactor cross-namespace Route-Gateway binding to: + +* Be more consistent with [cross-namespace references from + Routes](../gep-709/index.md) +* Provide a clear path to enable Route inclusion (Routes including Routes). +* Simplify user experience based on initial feedback. +* Enable other kinds of Route parents in addition to Gateway, this could include: + * Routes (as part of one potential approach to Route inclusion) + * Custom Gateway resources + * Mesh resources + +## Out of scope + +* Defining how Route inclusion will work. + +## Existing Approach + +The existing API already supports cross-namespace references. Gateways configure +the following: + +* A Route label selector +* Namespaces: Same, Selector, or All + +Routes then have three options as far as which Gateways can bind to them: + +* Same namespace (default) +* From a list of Gateways +* All + +Although this enables a great deal of flexibility, it can lead to confusion. For +example, 2 separate label selectors from Gateway can be challenging for users to +compute. It requires users to do to label selector lookups and then compute the +intersection of that result. Additionally, the default behavior of selecting all +Routes in the same namespace makes it easy to accidentally expose applications +(see [#515](https://github.com/kubernetes-sigs/gateway-api/issues/515)). + +## Proposed Changes + +Although the API changes proposed here are relatively small, this represents a +larger conceptual change. Instead of Gateways selecting Routes, Routes would +directly reference the Gateways they wanted to attach to. This pattern was +already possible with the existing API, but not clearly documented. + +One of the key concepts in the [cross-namespace references from Routes +GEP](../gep-709/index.md) was that of a handshake for +references that cross namespace boundaries. A key part of that handshake was +that one direction included a direct reference, while the other direction +provided a way to denote trust for a set of Namespaces and kind of resources. + +It seems to make sense to carry that same underlying principle through to the +Route - Gateway relationship. Given that each Gateway is likely to support many +Routes, it would not be practical to support direct references from Gateways to +Routes. Instead, it is simpler if Routes directly reference the Gateways they +want to attach to. Gateways can then specify the namespaces they trust Routes +to attach from. + +![Routes directly reference Gateway](images/724-proposal.png) + +In the following example, the lb Gateway indicates that it trusts Routes from +the foo Namespace, and the HTTPRoute in that namespace attaches directly to the +Gateway. + +```yaml +kind: Gateway +metadata: + name: lb + namespace: infra +spec: + listeners: + - name: foo + hostname: foo.com + port: 80 + routes: + namespaces: + from: Selector + selector: + kubernetes.io/metadata.name: foo +--- +kind: HTTPRoute +metadata: + name: foo + namespace: foo +spec: + attachTo: + - kind: Gateway + namespace: infra + name: lb + sectionName: foo + rules: + - name: abc + matches: + - path: /bar +``` + +## Rationale + +#### 1. Remove Complexity While it is Still Possible +A goal of v1alpha2 is to make any breaking changes we think we'll need to for +the lifetime of the API. After this release, we plan to provide a fully +convertible, and hopefully also fully backwards compatible, API. If we really +do need more advanced functionality in the future, it will be fairly +straightforward to add in a future release. On the other hand, it will be near +impossible to remove this complexity post-v1alpha2 if we were to leave it as is. + +#### 2. Route Selection Added Confusion and Did Not Enhance Security +Although it was easy to look at the selector from Gateway -> Route as providing +Gateway admins some form of control over the Routes attached to their Gateway, +it was nothing but security theater. Route owners still had ultimate control by +deciding how their Routes were labeled. This also made it difficult to document +how Gateway and Route owners should interact. One possible explanation was that +Gateway owners should provide Route owners with a set of labels that they should +add to their Route to bind to a given Gateway. At that point, we were still +ultimately relying on Route owners to attach a Route to a Gateway, just making +it a rather clunky process. + +It should be noted that this proposal does still retain the ability for Gateways +to restrict the namespaces they trust Routes to attach from. This was the only +real control Gateway admins had before this proposed change. + +#### 3. The Existing Defaults Were Too Permissive +One of the common complaints about the existing API was that the defaults made +it far too easy to accidentally expose a Route. By default, a Gateway would be +bound to all Routes in the same namespace. Although that made the getting +started guide simple, it would inevitably lead to some unfortunate mistakes in +the future. As we've already learned with Kubernetes, it's very difficult to +recover from insecure defaults. Instead, it's much safer to start with more +explicit configuration that demonstrates clear intent to connect resources. + +#### 4. We Need to Support non-Gateway Route Parents +With the expansion of this API, it's clear that a Route may have non-Gateway +parents. This may be other Routes, mesh implementations, or custom Gateways. +Although none of these concepts are well specified at this point, making this +change now will give us more flexibility in the future. + +#### 5. Users Want Control over the Gateways Their Routes Are Attached To +Initial feedback we've received has shown that users want to have very clear +control over the Gateways their Routes are attached to. Even in the case of +Gateway replacement, many Route owners would prefer to be involved in the +process. + +As we get more feedback and usage of the API, we may identify more users that +are interested in the more advanced capabilities that some form of selection may +enable, but at this point it's clear that a large portion of users value an +explicit way to attach a Route to a Gateway. + +#### 6. We Need to Maintain a Handshake Between Gateways and Routes +Of course we do still need a handshake that will enable cross-namespace +references between Routes and Gateways. This proposal leaves in the core +capabilities of the v1alpha1 API for this. Gateways can specify the namespaces +they trust Routes to bind from, and Routes directly reference the Gateways they +want to attach to. This is largely similar to the ReferenceGrant model proposed +for Route->Service references, but is embedded within the Route and Gateway +resources. The alternatives below explore what this could look like with +ReferenceGrant. + +## API Changes + +The proposed changes here can be summarized as: + +* Remove Route selector from the RouteBindingSelector in Gateway listeners. +* Replace Route kind and group with optional list of accepted kinds and groups + in RouteBindingSelector. +* Rename RouteBindingSelector to ListenerRoutes. +* Replace the 3 options from Route -> Gateway (All, FromList, SameNamespace) + with a reference list that supports arbitrary kinds. +* Add a name to Gateway listeners. +* Restructure listener status to include name, routeRefs, and supportedKinds + fields. + +### Gateway Spec + +In Gateway spec, the only change involves removing the Route selector field. +Everything else remains the same. + +#### Removed +The following fields would be removed from RouteBindingSelector: + +```go + // Selector specifies a set of route labels used for selecting + // routes to associate with the Gateway. If this Selector is defined, + // only routes matching the Selector are associated with the Gateway. + // An empty Selector matches all routes. + // + // Support: Core + // + // +optional + Selector *metav1.LabelSelector `json:"selector,omitempty"` + // Group is the group of the route resource to select. Omitting the value or specifying + // the empty string indicates the gateway.networking.k8s.io API group. + // For example, use the following to select an HTTPRoute: + // + // routes: + // kind: HTTPRoute + // + // Otherwise, if an alternative API group is desired, specify the desired + // group: + // + // routes: + // group: acme.io + // kind: FooRoute + // + // Support: Core + // + // +optional + // +kubebuilder:default=gateway.networking.k8s.io + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Group *string `json:"group,omitempty"` + // Kind is the kind of the route resource to select. + // + // Kind MUST correspond to kinds of routes that are compatible with the + // application protocol specified in the Listener's Protocol field. + // + // If an implementation does not support or recognize this + // resource type, it SHOULD set the "ResolvedRefs" condition to false for + // this listener with the "InvalidRoutesRef" reason. + // + // Support: Core + Kind string `json:"kind"` +``` + +#### Added +Note: The ListMapKey annotation for listeners would also have to change to name +for this. + +```go +type Listener struct { + // Name is the name of the Listener. If more than one Listener is present + // each Listener MUST specify a name. The names of Listeners MUST be unique + // within a Gateway. + // + // Support: Core + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +optional + Name *string `json:"name,omitempty"` + // ... +} +``` + +The RouteBindingSelector struct would be renamed to ListenerRoutes, and a Kinds +field would be added. Note that the Selector, Group, and Kind field would be +removed from this struct as described above. + +```go +type ListenerRoutes struct { + // ... + // Kinds specifies the groups and kinds of Routes that are allowed to bind to + // this Gateway listener. When unspecified or empty, the only limitation on + // the kinds of Routes supported is the Listener protocol. Kind MUST + // correspond to kinds of Routes that are compatible with the application + // protocol specified in the Listener's Protocol field. If an implementation + // does not support or recognize this resource type, it SHOULD set the + // "ResolvedRefs" condition to false for this listener with the + // "InvalidRoutesRef" reason. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=10 + Kinds []RouteGroupKind `json:"kinds,omitempty"` +} + +type RouteGroupKind struct { + // Group is the group of the Route. + // + // Support: Core + // + // +optional + // +kubebuilder:default=gateway.networking.k8s.io + // +kubebuilder:validation:MaxLength=253 + Group *string `json:"group,omitempty"` + // Kind is the kind of the Route. + // + // Support: Core + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Kind string `json:"kind"` +} +``` + +### Gateway Status +The most significant addition to the Gateway resource is in status. It may be +helpful to share a sample of what the YAML would look like: + +```yaml +status: + listeners: + - name: foo + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + attachedRoutes: 1 + conditions: + - ... +``` + +The key changes here all involve Listener status: + +* Replace the `port`, `protocol`, and `hostname` field with `name` to take + advantage of the new Listener name concept. +* Add a new `supportedKinds` field. This will be most useful when the + corresponding field in the spec is left blank or when a user specifies kinds + that a controller does not support. + +Note: The ListMapKey annotation for listener status would also have to change to +name for this. + +```go +// ListenerStatus is the status associated with a Listener. +type ListenerStatus struct { + // Name is the name of the Listener. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +optional + Name *string `json:"name,omitempty"` + + // SupportedKinds is the list indicating the Kinds supported by this + // listener. When this is not specified on the Listener, this MUST represent + // the kinds an implementation supports for the specified protocol. When + // there are kinds specified on the Listener, this MUST represent the + // intersection of those kinds and the kinds supported by the implementation + // for the specified protocol. + // + // +kubebuilder:validation:MaxItems=10 + // +optional + SupportedKinds []RouteGroupKind `json:"supportedKinds,omitempty"` + + // AttachedRoutes represents the total number of Routes that have been + // successfully attached to this Listener. + AttachedRoutes int32 `json:"attachedRoutes"` + + // Conditions... +} +``` + +### Routes + +On Routes, we remove the `RouteGateways` struct and replace it with a list of +parent references to attach to. + +#### Removed +From Route Specs: +```go + // Gateways defines which Gateways can use this Route. + // + // +optional + // +kubebuilder:default={allow: "SameNamespace"} + Gateways *RouteGateways `json:"gateways,omitempty"` +``` + +And the structs that references: +```go +// RouteGateways defines which Gateways will be able to use a route. If this +// field results in preventing the selection of a Route by a Gateway, an +// "Admitted" condition with a status of false must be set for the Gateway on +// that Route. +type RouteGateways struct { + // Allow indicates which Gateways will be allowed to use this route. + // Possible values are: + // * All: Gateways in any namespace can use this route. + // * FromList: Only Gateways specified in GatewayRefs may use this route. + // * SameNamespace: Only Gateways in the same namespace may use this route. + // + // +optional + // +kubebuilder:validation:Enum=All;FromList;SameNamespace + // +kubebuilder:default=SameNamespace + Allow *GatewayAllowType `json:"allow,omitempty"` + + // GatewayRefs must be specified when Allow is set to "FromList". In that + // case, only Gateways referenced in this list will be allowed to use this + // route. This field is ignored for other values of "Allow". + // + // +optional + GatewayRefs []GatewayReference `json:"gatewayRefs,omitempty"` +} +``` + +#### Added +To Route Specs: +```go + // ParentRefs references the resources that can attach to this Route. The only + // kind of parent resource with "Core" support is Gateway. This API may be + // extended in the future to support additional kinds of parent resources such + // as one of the route kinds. It is invalid to reference an identical parent + // more than once. It is valid to reference multiple distinct sections within + // the same parent resource, such as 2 Listeners within a Gateway. + // + // It is possible to separately reference multiple distinct objects that may + // be collapsed by an implementation. For example, some implementations may + // choose to merge compatible Gateway Listeners together. If that is the case, + // the list of routes attached to those resources should also be merged. + // + // +optional + // +kubebuilder:validation:MaxItems=16 + ParentRefs []ParentRef `json:"parentRefs,omitempty"` +``` + +And the struct that references: +```go +// ParentRef identifies an API object that should be considered a parent of this +// resource. The only kind of parent resource with "Core" support is Gateway. +// This API may be extended in the future to support additional kinds of parent +// resources, such as HTTPRoute. +type ParentRef struct { + // Group is the group of the referent. + // + // Support: Core + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:default=gateway.networking.k8s.io + Group string `json:"group"` + + // Kind is kind of the referent. + // + // Support: Core (Gateway) + // Support: Extended (Other Resources) + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:default=Gateway + // +optional + Kind *string `json:"kind,omitempty"` + + // Namespace is the namespace of the referent. When unspecified (empty + // string), this will either be: + // + // * local namespace of the target is a namespace scoped resource + // * no namespace (not applicable) if the target is cluster-scoped. + // + // Support: Extended + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +optional + Namespace *string `json:"namespace,omitempty"` + + // Scope represents if this refers to a cluster or namespace scoped resource. + // This may be set to "Cluster" or "Namespace". + // + // Support: Core (Namespace) + // Support: Extended (Cluster) + // + // +kubebuilder:validation:Enum=Cluster;Namespace + // +kubebuilder:default=Namespace + // +optional + Scope *string `json:"scope,omitempty"` + + // Name is the name of the referent. + // + // Support: Core + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Name string `json:"name"` + + // SectionName is the name of a section within the target resource. In the + // following resources, SectionName is interpreted as the following: + // + // * Gateway: Listener Name + // + // Implementations MAY choose to support attaching Routes to other resources. + // If that is the case, they MUST clearly document how SectionName is + // interpreted. + // + // When unspecified (empty string), this will reference the entire resource. + // For the purpose of status, an attachment is considered successful if at + // least one section in the parent resource accepts it. For example, Gateway + // listeners can restrict which Routes can bind to them by Route kind, + // namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + // the referencing Route, the Route MUST be considered successfully + // attached. If no Gateway listeners accept attachment from this Route, the + // Route MUST be considered detached from the Gateway. + // + // Support: Core + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +optional + SectionName *string `json:"sectionName,omitempty"` +} +``` + +#### Changed + +To accommodate Routes with arbitrary types of parents, `RouteGatewayStatus` would +be renamed to `RouteParentStatus`. Similarly, the `GatewayRef` inside that +struct would be replaced with the `ParentRef` struct included above. + +### Advantages + +* Simplifies the API by providing a single way to attach Routes to Gateway. +* Assigns clear responsibilities to Gateway and Route owners. +* Consistent with pattern of direct references from Routes to all associated + resources. +* Enables attaching Routes to arbitrary parents, such as custom Gateways, other + Routes (to be defined), or Meshes. +* Prevents accidental exposure of Routes. +* Easy to understand which Gateways/parents a Route is attached to. +* Further simplifies path to Route inclusion. +* Follows pattern of direct reference in one direction with a broader trust + reference in the other direction. +* Aligns with initial user feedback. + +### Disadvantages + +* Attaching a Route to a named listener with SectionName may be a bit confusing. +* Does not utilize existing ReferenceGrant mechanism. +* May be more difficult to understand which Routes are attached to a Gateway. +* Adding/replacing a Gateway requires changes to Routes. + +### Potential Expansion +In the future, it may be useful to add a selector from Route -> Parent. Although +this would enable greater flexibility, it also significantly increases +complexity. + +## Alternatives + +### 1. ReferenceGrant with Gateways selecting Routes + +![ReferenceGrant with Gateways selecting Routes](images/724-alt1.png) + +A compelling alternative to this proposal would involve retaining the Route +selector in Gateway and replacing the trust concept in Routes with +ReferenceGrant. To represent the same example as above, we'd use a Route +selector on Gateway, a corresponding label on the HTTPRoute, and a +ReferenceGrant that allowed it: + +```yaml +kind: Gateway +metadata: + name: xlb + namespace: infra +spec: + listeners: + - name: foo + hostname: foo.com + port: 80 + routes: + kind: HTTPRoute + selector: + gateway: xlb + namespaces: + from: Selector + selector: + kubernetes.io/metadata.name: foo +--- +kind: HTTPRoute +metadata: + name: foo + namespace: foo + labels: + gateway: xlb +spec: + rules: + - name: abc + matches: + - path: /bar +--- +kind: ReferenceGrant +metadata: + name: infra-gateways + namespace: foo +spec: + from: + - group: gateway.networking.k8s.io + kind: Gateway + namespace: infra + to: + - group: gateway.networking.k8s.io + kind: HTTPRoute +``` + +#### Advantages + +* Consistent use of ReferenceGrant throughout the API. +* Provides a single way of binding Gateways to Routes. + +#### Disadvantages + +* Even the simplest cross-namespace reference from Gateway -> Route would + require a ReferenceGrant in each target namespace. +* Existing demos and examples would become significantly more verbose. +* Does not support attaching Routes to arbitrary parents. +* Does not prevent accidental exposure of Routes. +* Route owners have limited control in terms of which Gateways their Route is + attached to. + +### 2. ReferenceGrant with Routes referencing Gateways + +![ReferenceGrant with Routes referencing Gateways](images/724-alt2.png) + +The other way we could use ReferenceGrant would be with Routes referencing +Gateways. Unfortunately the nested structure of Gateways makes this nearly +impossible to do effectively. A core concept for Gateways is that each listener +should be able to attach to an entirely different set of Routes. For example, +a Gateway may want to delegate foo.com to the foo namespace and bar.com to the +bar namespace. Unfortunately that would be very difficult to recreate with +ReferenceGrant. + +ReferenceGrant is fundamentally about trusting references from resource of kind +Foo in resources of kind Bar. Names and section names are intentionally +excluded. If we added both of those concepts to ReferenceGrant, this would be +possible, but quite complex and verbose. This is what the example from above +would look like with this approach: + +```yaml +kind: Gateway +metadata: + name: lb + namespace: infra +spec: + listeners: + - name: foo + hostname: foo.com + port: 80 +--- +kind: ReferenceGrant +metadata: + name: foo-lb + namespace: infra +spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: foo + to: + - group: gateway.networking.k8s.io + kind: Gateway + name: lb + sectionName: foo +--- +kind: HTTPRoute +metadata: + name: foo + namespace: foo +spec: + parentRefs: + - kind: Gateway + namespace: infra + name: lb + sectionName: foo + rules: + - name: abc + matches: + - path: /bar +``` + +#### Advantages + +* Consistent use of ReferenceGrant throughout the API. +* Provides a single way of binding Gateways to Routes. +* Supports attaching Routes to arbitrary parents. +* Prevents accidental exposure of Routes. + +#### Disadvantages + +* In most cases, each listener in a Gateway would require a unique + ReferenceGrant resource. +* Even the simplest cross-namespace reference from Route -> Gateway would + require a ReferenceGrant in each target namespace. This could either rule + out or significantly complicate self-service use-cases. +* Existing demos and examples would become significantly more verbose. +* ReferenceGrant would become more complex for all other use cases. + +## References + +**GEPs** + +* [GEP 709: ReferenceGrant + Cross Namespace References from Routes](../gep-709/index.md) + +**Docs:** + +* [Gateway API References Doc](https://docs.google.com/document/d/18MoabVA-fr5XL9cYdf6cxclqRwFpOvHUXV_UYzSiooY/edit) +* [Simplifying Gateway Route Binding](https://docs.google.com/document/d/1YVyB2dizACWrn8Rj31hQFBwCYqgyFKsxKeeGlv-iQCs/edit) + +**Issues:** + +* [Simplify Gateway Route Binding](https://github.com/kubernetes-sigs/gateway-api/issues/594) +* [Route selector improvements on Gateway](https://github.com/kubernetes-sigs/gateway-api/issues/515) diff --git a/site-src/ko/geps/gep-724/metadata.yaml b/site-src/ko/geps/gep-724/metadata.yaml new file mode 100644 index 0000000000..f7adba2c24 --- /dev/null +++ b/site-src/ko/geps/gep-724/metadata.yaml @@ -0,0 +1,7 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 724 +name: Refresh Route-Gateway Binding +status: Standard +authors: + - robscott diff --git a/site-src/ko/geps/gep-726/index.md b/site-src/ko/geps/gep-726/index.md new file mode 100644 index 0000000000..7e4a04bd4b --- /dev/null +++ b/site-src/ko/geps/gep-726/index.md @@ -0,0 +1,320 @@ +# GEP-726: Add Path Redirects and Rewrites + +* Issue: [#726](https://github.com/kubernetes-sigs/gateway-api/issues/726) +* Status: Standard + +## TLDR + +This GEP proposes adding support for path redirects and rewrites in addition to +host rewrites. This would augment the existing host redirection capabilities. + +## Goals + +* Implement path redirects. +* Implement the most portable and simple forms of path rewrites. +* Describe how more advanced rewrite and redirect and redirect capabilities + could be added in the future. + +## API + +Although many implementations support very advanced rewrite and redirect +capabilities, the following are the most [portable](#portability) concepts that +are not already supported by the Gateway API: + +* Path redirects +* Path prefix redirects +* Path prefix rewrites +* Host rewrites + +Although regular expression based redirects and rewrites are commonly supported, +there is significantly more variation in both if and how they are implemented. +Given the wide support for this concept, it is important to design the API in a +way that would make it easy to add this capability in the future. + +### Path Modifiers + +Both redirects and rewrites would share the same `PathModifier` types: + +```go +// HTTPPathModifierType defines the type of path redirect. +type HTTPPathModifierType string + +const ( + // This type of modifier indicates that the complete path will be replaced by + // the path redirect value. + AbsoluteHTTPPathModifier HTTPPathModifierType = "Absolute" + + // This type of modifier indicates that any prefix path matches will be + // replaced by the substitution value. For example, a path with a prefix match + // of "/foo" and a ReplacePrefixMatch substitution of "/bar" will have the + // "/foo" prefix replaced with "/bar" in matching requests. + PrefixMatchHTTPPathModifier HTTPPathModifierType = "ReplacePrefixMatch" +) + +// HTTPPathModifier defines configuration for path modifiers. +type HTTPPathModifier struct { + // Type defines the type of path modifier. + // + // +kubebuilder:validation:Enum=Absolute;ReplacePrefixMatch + Type HTTPPathModifierType `json:"type"` + + // Substitution defines the HTTP path value to substitute. An empty value ("") + // indicates that the portion of the path to be changed should be removed from + // the resulting path. For example, a request to "/foo/bar" with a prefix + // match of "/foo" would be modified to "/bar". + // + // +kubebuilder:validation:MaxLength=1024 + Substitution string `json:"substitution"` +} +``` + +### Redirects + +The existing `RequestRedirect` filter can be expanded to support path redirects. +In the following example, a request to `/foo/abc` would be redirected to +`/bar/abc`. + +```yaml +kind: HTTPRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: http-filter-1 +spec: + rules: + - matches: + - path: + type: Prefix + value: /foo + filters: + - type: RequestRedirect + requestRedirect: + hostname: foo.com + path: + type: ReplacePrefixMatch + value: /bar +``` + +This would be represented with the following API addition to the existing +HTTPRequestRedirect filter: +```go +// HTTPRequestRedirect defines a filter that redirects a request. At most one of +// these filters may be used on a Route rule. This may not be used on the same +// Route rule as a HTTPRequestRewrite filter. +// +// Support: Extended +type HTTPRequestRedirect struct { + // Path defines a path redirect. + // + // Support: Extended + // + // +optional + Path *HTTPPathModifier `json:"path,omitempty"` + // ... +} +``` + +### Rewrites + +A new `URLRewrite` filter can be added to support rewrites. In the following +example, a request to `example.com/foo/abc` would be rewritten to +`example.net/bar/abc`. + +```yaml +kind: HTTPRoute +apiVersion: gateway.networking.k8s.io/v1alpha2 +metadata: + name: http-filter-1 +spec: + hostnames: + - example.com + rules: + - matches: + - path: + type: Prefix + value: /foo + filters: + - type: URLRewrite + requestRewrite: + hostname: example.net + path: + type: ReplacePrefixMatch + substitution: /bar +``` + +This would be represent with the following API additions: +```go +// HTTPURLRewrite defines a filter that modifies a request during forwarding. +// At most one of these filters may be used on a Route rule. This may not be +// used on the same Route rule as a HTTPRequestRedirect filter. +// +// Support: Extended +type HTTPURLRewrite struct { + // Hostname is the value to be used to replace the Host header value during + // forwarding. + // + // Support: Extended + // + // +optional + // +kubebuilder:validation:MaxLength=255 + Hostname *string `json:"hostname,omitempty"` + + // Path defines a path rewrite. + // + // Support: Extended + // + // +optional + Path *HTTPPathModifier `json:"path,omitempty"` +} +``` + +Note: `RequestRewrite` was originally considered as a name for this filter. +`URLRewrite` was chosen as it more clearly represented the capabilities of the +filter and would not be confused with header or query param modification. + +## Portability + +When considering what should be possible in the API, it's worth evaluating what +common tooling is capable of. This is by no means a complete list, but this +provides a high level overview of how this is configured across different +implementations. + +Although not all of these implementations directly support prefix rewrites or +redirects, the ones that don't include regular expression support which can be +used to implement prefix rewrites and redirects. + +Note: This section intentionally excludes the redirect capabilities already +contained in the API. + +### Envoy +Envoy supports the following relevant capabilities +([reference](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto)): + +* path_redirect (redirect only) +* prefix_rewrite (redirect and forwarding) +* regex_rewrite (redirect and forwarding) +* host_rewrite_literal (forwarding only) +* strip_query (redirect only) + +Note that path rewrite relies on the prefix match for the route, there is not +a way to differentiate between the prefix used for matching and rewriting. + +### Google Cloud +Google Cloud URL Maps support the following relevant capabilities +([reference](https://cloud.google.com/compute/docs/reference/rest/v1/urlMaps)): + +* pathPrefixRewrite (forwarding only) +* hostRewrite (forwarding only) +* pathRedirect (redirect only) +* prefixRedirect (redirect only) +* stripQuery (redirect only) + +Note that path rewrite relies on the prefix match for the route, there is not +a way to differentiate between the prefix used for matching and rewriting. + +### HAProxy +HAProxy supports the following relevant capabilities +([reference](https://cbonte.github.io/haproxy-dconv/2.5/configuration.html)): + +* http-request set-path (advanced path rewrite capabilities) +* http-request replace-path (rewrites entire path) +* http-request replace-pathq (rewrites entire path + query string) +* http-request replace-uri (URI rewrite based on input regex) +* redirect location (advanced redirect capabilities) + +### NGINX +The NGINX rewrite module contains the following relevant capabilities +([reference](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html)): + +* PCRE regex based rewrites +* Rewrite directive can be used during forwarding or redirects +* Rewrite directive can affect host, path, or both +* Rewrite directive can be chained + +## Future Extension +There are two relatively common types of path rewrite/redirect that are not +covered by this proposal: + +1. Replace a path prefix separate from the match +2. Replace with a Regular Expression substitution + +Both of the following can be represented by adding a new field new types. For +example, this config would result in a request to `/foo/baz` to be rewritten to +`/bar/baz`: + +```yaml +filters: +- type: RequestRewrite + requestRewrite: + path: + type: ReplacePrefix + pattern: /foo + substitution: /bar +``` + +Similarly, this config would result in a request to `/foo/bar/baz` being +rewritten to `/foo/other/baz`. +```yaml +filters: +- type: RequestRewrite + requestRewrite: + path: + type: RegularExpression + pattern: /foo/(.*)/baz + substitution: other +``` + +Although both of the above are natural extensions of the API, they are not quite +as broadly supported. For that reason, this GEP proposes omitting these types +from the initial implementation. + +## Alternatives + +### 1. Generic Path Match Replacement +Instead of the `ReplacePrefixMatch` option proposed above, we could have a +`ReplacePathMatch` option. This would provide significantly more flexibility and +room for growth than prefix replacement. + +Unfortunately it would be difficult to represent conformance and support levels. +It also would have limited value. Replacing "Exact" match types would be nearly +identical to the "Absolute" match type, and replacing "RegularExpression" match +types would likely not yield the desired result. In most cases, RegEx rewrites +are implemented separately from RegEx path matching. So a user may want to match +all paths matching one RegEx, but use a separate RegEx + substitution value for +rewrites. + +It is theoretically possible that future patch match types could be useful as a +rewrite source, but the common proxies described above seem to be limited to the +rewrite types described above. + +### 2. Top Level Rewrite Fields +Although a small difference, we could restructure how the path rewrites and +redirects were configured. One example would be adding top level fields in the +filters for each kind of path rewrite or redirect. That would result in a change +like this: + +**Before:** +```yaml +requestRewrite: + hostname: foo.com + path: + type: Prefix + substitution: /bar +``` + +**After:** +```yaml +requestRewrite: + hostname: foo.com + pathPrefix: /bar +``` + +Although simpler for the initial use cases, it may become more difficult to +maintain and validate as additional types of rewrites and redirects were added. + + +## References + +Issues: + +- [#200: Add support for configurable HTTP redirects](https://github.com/kubernetes-sigs/gateway-api/issues/200) +- [#678: Add support for HTTP rewrites](https://github.com/kubernetes-sigs/gateway-api/issues/678) diff --git a/site-src/ko/geps/gep-726/metadata.yaml b/site-src/ko/geps/gep-726/metadata.yaml new file mode 100644 index 0000000000..a25826ba51 --- /dev/null +++ b/site-src/ko/geps/gep-726/metadata.yaml @@ -0,0 +1,7 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 726 +name: Add Path Redirects and Rewrites +status: Standard +authors: + - robscott diff --git a/site-src/ko/geps/gep-735/index.md b/site-src/ko/geps/gep-735/index.md new file mode 100644 index 0000000000..b7a634b9a0 --- /dev/null +++ b/site-src/ko/geps/gep-735/index.md @@ -0,0 +1,212 @@ +# GEP-735: TCP and UDP addresses matching + +* Issue: [#735](https://github.com/kubernetes-sigs/gateway-api/issues/735) +* Status: Declined + +## Notes about declined status + +At one point before the release of `v0.5.0` we did have an implementation +of this GEP in `main`, but we decided to pull back on it for multiple +reasons: + +- operated too much like WAF/firewall functionality, which is not in scope +- no implementations championing the use case + +It should also be noted that the maintainers have at least considered the +idea of an `IPRoute` API which would help differentiate this from firewall +functionality, however there haven't been any strong champions for such a +use case for this either. + +As such this GEP is marked as `Declined` to make it clear to readers that +presently we don't have plans to include this in any future release. Keep +in mind that this doesn't mean that we wouldn't consider it again as a +future feature however: if you're interested in this functionality please +feel free to start a new [github discussion][disc] and/or feel free to +create a new PR updating this GEP with your use case(s) and context. + +[disc]:https://github.com/kubernetes-sigs/gateway-api/discussions + +## TLDR + +Spec for matching source and destination addresses on L4 APIs. + +## Goals + +- add matching rules for address to `TCPRoute` +- add matching rules for address to `UDPRoute` +- intentionally avoid type definitions that would make it hard to expand later + +## Non-Goals + +- define rules for port matching + +## Introduction + +While `TCPRoute` and `UDPRoute` currently support custom matching extensions, +there is desire among the community to include some "fundamental" matching +options in the spec that cover the most common requirements. In this GEP we +request address matching for these APIs in order to support a standard +for some of the commonplace setups of gateway implementations. Matching is +intended to be covered for both _source_ and _destination_ to enable a finer +level of tuning options for L4 traffic routing at a level below the `Gateway`. + +## API + +The API changes include the following new types: + +- `AddressMatch` to indicate the IP for address matching +- `AddressRouteMatches` to configure matching according to network address + +These types enable the address matching required, with some active +considerations about how to leave these open ended for later expansion. + +### AddressMatch Type + +A new `AddressMatch` type provides the targeting mechanism for match inclusion +of a given network address: + +```go +type AddressMatch struct { + // Type of the address, either IPAddress or NamedAddress. + // + // If NamedAddress is used this is a custom and specific value for each + // implementation to handle (and add validation for) according to their + // own needs. + // + // For IPAddress the implementor may expect either IPv4 or IPv6. + // + // Support: Core (IPAddress) + // Support: Implementation-specific (NamedAddress) + // + // +optional + // +kubebuilder:validation:Enum=IPAddress;NamedAddress + // +kubebuilder:default=IPAddress + Type *AddressType `json:"type,omitempty"` + + // Value of the address. The validity of the values will depend + // on the type and support by the controller. + // + // If implementations support proxy-protocol (see: + // https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) they + // must respect the connection metadata from proxy-protocol + // in the match logic implemented for these address values. + // + // Examples: `1.2.3.4`, `128::1`, `my-named-address`. + // + // Support: Core + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Value string `json:"value"` +} +``` + +### AddressRouteMatches Type + +Using the new `AddressMatch` type matches can be expressed in topical lists on +`TCPRoute` and `UDPRoute` using the new `AddressRouteMatches` type: + +```go +type AddressRouteMatches struct { + // SourceAddresses indicates the originating (source) network + // addresses which are valid for routing traffic. + // + // Support: Core + SourceAddresses []AddressMatch `json:"sourceAddresses"` + + // DestinationAddresses indicates the destination network addresses + // which are valid for routing traffic. + // + // Support: Core + DestinationAddresses []AddressMatch `json:"destinationAddresses"` +} +``` + +This type becomes an optional field and shared by both `TCPRouteRule` and +`UDPRouteRule` as a list: + +```go +type TCPRouteRule struct { + // Matches add rules for filtering traffic to backends based on addresses. + // + // +optional + Matches []AddressRouteMatches `json:"matches,omitempty"` +} +``` + +Each element in `[]AddressRouteMatches` should be implemented as an `OR` style +match (e.g. the inbound traffic matches as long as at least one of the separate +`AddressRouteMatches` rules is matched). + +The above would make the following YAML examples possible: + +```yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TCPRoute +metadata: + name: matching +spec: + rules: + - matches: + - sourceAddresses: + - value: "192.168.1.1" + - value: "FE80::0202:B3FF:FE1E:8329" + - type: NamedAddress + value: "my-custom-name" + destinationAddresses: + - value: "10.96.0.1" + backendRefs: + - name: my-service + port: 8080 +``` + +## Alternatives + +### Pure Gateway Mode + +Technically the existing specification supported this kind of matching through +`Gateway` object `Listeners` and it was considered to simply document that +further and expand upon it, but in a desire to better support more complex +setups that are becoming commonplace in the ecosystem (e.g. service mesh) there +was sufficient cause to add this functionality at the route level. + +### Copying NetworkPolicy + +After the first draft of this document we consulted the `NetworkPolicy` API to +determine if there were enough similarities to copy some of the semantics there +to here. Both the [existing API][k8s-net] and (at the time of writing) the +[upcoming API][pol-new] were reviewed. Ultimately some influence was taken from +`NetworkPolicyPort` to define the `PolicyMatch` structure here, but some ideas +such as binding ports and network addresses together in a single struct did not +seem necessary as the `RuleAction` present in policy did not seem applicable +for this work at the time. We may want to revisit this as the new policy work +merges and matures. + +[k8s-net]:https://github.com/kubernetes/kubernetes/blob/1e6f3b5cd68049a3501782af8ff3ddd647d0b408/pkg/apis/networking/types.go#L95 +[pol-new]:https://github.com/kubernetes/enhancements/pull/2522 + +### Port Matching + +While we were able to think of some cases for port matching, the constraints of +listeners for the Gateway make it much harder to understand the value at this +stage. We're deferring port matching to focus on address matching for this +iteration so that we can come back around to it separately once we've gathered +more use case information. + +### CIDR AddressType + +When using `AddressType` as a component to `AddressMatch` it was considered to +add a new type `CIDRAddress` which would allow matching against an entire +subnet. This sounds good, but given a lack of concrete feedback on an +immediate need for this in the original issue [#727][issue-727] it was decided +that this could wait for now and just as easily be added later in a backwards +compatible manner. + +[issue-727]:https://github.com/kubernetes-sigs/gateway-api/issues/727 + +## References + +A related conversation in [#727][issue-727] ultimately instigated these +new requirements and may be helpful to review. + +[issue-727]:https://github.com/kubernetes-sigs/gateway-api/issues/727 diff --git a/site-src/ko/geps/gep-735/metadata.yaml b/site-src/ko/geps/gep-735/metadata.yaml new file mode 100644 index 0000000000..7faab03777 --- /dev/null +++ b/site-src/ko/geps/gep-735/metadata.yaml @@ -0,0 +1,7 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 735 +name: TCP and UDP addresses matching +status: Declined +authors: + - shaneutt diff --git a/site-src/ko/geps/gep-746/index.md b/site-src/ko/geps/gep-746/index.md new file mode 100644 index 0000000000..7175c98d8d --- /dev/null +++ b/site-src/ko/geps/gep-746/index.md @@ -0,0 +1,265 @@ +# GEP-746: Replace Cert Refs on HTTPRoute with Cross Namespace Refs from Gateway + +* Issue: [#746](https://github.com/kubernetes-sigs/gateway-api/issues/746) +* Status: Standard + +## TLDR + +This GEP proposes that we should remove TLS Certificate references from +HTTPRoute and replace them with Cross Namespace Certificate references from +Gateways. Although that is not a complete replacement on its own, this GEP shows +how a controller could provide the rest of the functionality with this approach. + +## Goals + +* Remove a confusing and underspecified part of the API - cert refs on + HTTPRoute. +* Add the ability to reference certificates in other namespaces from Gateways + to replace much of the functionality that was enabled by cert refs on + HTTPRoute. +* Describe how a controller could automate self service cert attachment to + Gateway listeners. + +## Non-Goals + +* Actually provide a core implementation of a controller that can enable self + service cert attachment. This may be worth considering at a later point, but + is out of scope for this GEP. + +## Introduction + +TLS Certificate references on HTTPRoute have always been a confusing part of the +Gateway API. In the v1alpha2 release, we should consider removing this feature +while we still can. This GEP proposes an alternative that is simpler to work +with and understand, while also leaving sufficient room to enable all the same +capabilities that certificate references on HTTPRoute enabled. + +### Attaching TLS Certificates with Routes is Confusing +One of the most confusing parts of the Gateway API is how certificates can be +attached to Routes. There are a variety of different factors that lead to +confusion here: + +* It can be natural to assume that a certificate attached to a Route only + applies to that Route. In reality, it applies to the entire listener(s) + associated with that Route. +* This means that a Route can affect any other Routes attached to the same + Gateway Listener. By attaching a Route to a Gateway Listener, you’re + implicitly trusting all other Routes attached to that Gateway Listener. +* When multiple Routes specify a certificate for the same Listener, it’s + possible that they will conflict and create more confusion. + +### Why We Did It +To understand how we ended up with the ability to attach TLS certificates with +Routes, it’s helpful to look at the use cases for this capability: + +1. Some users want Route owners to be able to attach arbitrary domains and certs + to a Gateway listener. + [#103](https://github.com/kubernetes-sigs/gateway-api/issues/103) +1. Some users want Route owners to control certs for their applications. + +### Alternative Solutions + +#### 1. Automation with tools like Cert-Manager +When automation is acceptable, the first use case is entirely possible with +tools like cert-manager that can watch Routes, generate certs for them, and +attach them to a Gateway. + +#### 2. Cross Namespace Cert Direct References from Gateways +With the already established ReferenceGrant concept, we have established a safe +way to reference resources across namespaces. Although this would require some +coordination between Gateway and App owners, it would enable App owners to +retain full control of the certs used by their app without the extra confusion +that certs in HTTPRoute have led to. + +### Enabling Self-Service Certificate Attachment for App Owners +Although this dramatically simplifies the API, it does not completely replace +the functionality that certs attached to HTTPRoutes enabled. Most notably, it +would be difficult to attach arbitrary self-provided certificates to a Gateway +listener without requiring manual changes from a Gateway admin. + +There are a couple potential solutions here: + +#### 1. Implement a selector for cert references instead of direct references +Although the simplicity of this approach is nice, it ends up with many of the +same problems as certificates attached to Routes have and feels inconsistent +with how Routes attach to Gateways. + +#### 2. Implement a controller that attaches certificates to Gateway listeners +Similar to cert-manager, it could be possible to implement a controller that +watches for Secrets with a certain label, and attaches those to the specified +Gateway. Although it's out of scope for this GEP to completely define what a +controller like this could look like, it would likely need to include at least +one of the following safeguards: + +1. A way to configure which namespaces could attach certificates for each + domain. +2. A way to configure which namespaces could attach certificates to each + Gateway (or Listener). +3. A way to use ReferenceGrant to indicate where references from Secrets to + Gateways were trusted from and to. + +## API + +The API changes proposed here are quite small, mostly removing fields. + +### Changes +1. The `LocalObjectReference` used for the `CertificateRef` field in + `GatewayTLSConfig` would be replaced with an `ObjectReference`. +1. `ReferenceGrant` would be updated to note that references from Gateways to + Secrets were part of the Core support level. + +### Removals + +From HTTPRouteSpec: +```go + // TLS defines the TLS certificate to use for Hostnames defined in this + // Route. This configuration only takes effect if the AllowRouteOverride + // field is set to true in the associated Gateway resource. + // + // Collisions can happen if multiple HTTPRoutes define a TLS certificate + // for the same hostname. In such a case, conflict resolution guiding + // principles apply, specifically, if hostnames are same and two different + // certificates are specified then the certificate in the + // oldest resource wins. + // + // Please note that HTTP Route-selection takes place after the + // TLS Handshake (ClientHello). Due to this, TLS certificate defined + // here will take precedence even if the request has the potential to + // match multiple routes (in case multiple HTTPRoutes share the same + // hostname). + // + // Support: Core + // + // +optional + TLS *RouteTLSConfig `json:"tls,omitempty"` +``` + +And the associated struct: +```go +// RouteTLSConfig describes a TLS configuration defined at the Route level. +type RouteTLSConfig struct { + // CertificateRef is a reference to a Kubernetes object that contains a TLS + // certificate and private key. This certificate is used to establish a TLS + // handshake for requests that match the hostname of the associated HTTPRoute. + // The referenced object MUST reside in the same namespace as HTTPRoute. + // + // CertificateRef can reference a standard Kubernetes resource, i.e. Secret, + // or an implementation-specific custom resource. + // + // Support: Core (Kubernetes Secrets) + // + // Support: Implementation-specific (Other resource types) + // + CertificateRef LocalObjectReference `json:"certificateRef"` +} +``` + +From GatewayTlsConfig: +```go + // RouteOverride dictates if TLS settings can be configured + // via Routes or not. + // + // CertificateRef must be defined even if `routeOverride.certificate` is + // set to 'Allow' as it will be used as the default certificate for the + // listener. + // + // Support: Core + // + // +optional + // +kubebuilder:default={certificate:Deny} + RouteOverride *TLSOverridePolicy `json:"routeOverride,omitempty"` +``` + +And the associated types: +```go +type TLSRouteOverrideType string + +const ( + // Allows the parameter to be configured from all routes. + TLSRouteOverrideAllow TLSRouteOverrideType = "Allow" + + // Prohibits the parameter from being configured from any route. + TLSRouteOverrideDeny TLSRouteOverrideType = "Deny" +) + +// TLSOverridePolicy defines a schema for overriding TLS settings at the Route +// level. +type TLSOverridePolicy struct { + // Certificate dictates if TLS certificates can be configured + // via Routes. If set to 'Allow', a TLS certificate for a hostname + // defined in a Route takes precedence over the certificate defined in + // Gateway. + // + // Support: Core + // + // +optional + // +kubebuilder:default=Deny + Certificate *TLSRouteOverrideType `json:"certificate,omitempty"` +} +``` + +## Prior Art + +OpenShift already supports configuring TLS certificates on Routes. Although +largely similar to the Gateway API approach, there are some notable differences: + +* Each Route can specify a maximum of 1 hostname +* When a Route is attached to a hostname, newer Routes can't use the same + hostname unless all of the following are true: + * The Routes are in the same namespace or the Router is configured to allow + sharing hostnames across namespaces + * The Routes have unique, non-overlapping paths specified + * The Routes are not TCP or TLS routes + +A typical configuration would involve a Router with `*.example.com` that has a +wildcard cert. Routes could be attached within those constraints without the +need for a cert. Routes can also use a different hostname if they also provide a +cert. + +## Alternatives + +### 1. Improved Documentation + Extended Support Level +My first attempt to improve this was to create a +[PR](https://github.com/kubernetes-sigs/gateway-api/pull/739) that would clarify +the documentation around how this works and lower the support level to extended. + +Trying to improve the documentation around this feature made it clear how easy +it would be to get confused by how it worked. It would be only natural to assume +that a cert attached to a Route would only apply to that Route. The conflict +resolution semantics associated with this were both complicated and difficult to +surface to a user through status or other means. + +Lowering the support level from core to extended also didn't make sense. +Although some implementers were uncomfortable with supporting this feature due +to the potential for vulnerabilities, that was not a sufficient reason to lower +the support level. An extended support level should only be used for features +that cannot be universally supported. That was not the case here. Instead there +were just very real questions around the safety of the feature. + +The combination of those 2 factors led me to believe that this feature was not +well thought out and should be removed. Since this was essentially just a +shortcut to attaching certificates to a Gateway listener from different sources, +it seemed like there had to be a way that was both safer and easier to +understand. That led to this proposal. + +### 2. Implement Hostname Restrictions +Similar to the OpenShift approach described above, we could enforce the +following: + +1. Only a single hostname may be specified for HTTPRoutes with a certificate + reference. +1. The oldest HTTPRoute to attach a certificate to a hostname would effectively + own that hostname. No other HTTPRoutes could be attached with the same + hostname unless they were explicitly allowed by that HTTPRoute. + +The second condition would be difficult to validate. As we've seen elsewhere in +the API, it's difficult to determine which resource was first to claim a +hostname or path. Instead we have to rely on the oldest resource, which can +result in some weird and potentially breaking changes if an older resource +chooses to claim a hostname. + +## References + +Docs: + +* [Gateway API: Replacing TLS Certificates in Routes](https://docs.google.com/document/d/1Cv95XFCL6S_9pIyS0drnsDLsfinWc2tHOFl_x3-_SWI/edit) diff --git a/site-src/ko/geps/gep-746/metadata.yaml b/site-src/ko/geps/gep-746/metadata.yaml new file mode 100644 index 0000000000..4b0f16a25d --- /dev/null +++ b/site-src/ko/geps/gep-746/metadata.yaml @@ -0,0 +1,7 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 746 +name: Replace Cert Refs on HTTPRoute with Cross Namespace Refs from Gateway +status: Standard +authors: + - robscott diff --git a/site-src/ko/geps/gep-820/index.md b/site-src/ko/geps/gep-820/index.md new file mode 100644 index 0000000000..78b92a9424 --- /dev/null +++ b/site-src/ko/geps/gep-820/index.md @@ -0,0 +1,62 @@ +# GEP-820: Drop extension points from Route matches + +* Issue: [#820](https://github.com/kubernetes-sigs/gateway-api/issues/820) +* Status: Standard + +## TLDR + +Drop extension points within Route match block. These extension points are +not well understood. + +## Goals + +- Drop the extension points within Route match block. + +## Non-Goals + +- Figure out a replacement solution for the use-case that these extension + points addressed + +## Introduction + +As the API moves towards `v1alpha2`, the maintainers intend to make the API +standard and forward compatible for the foreseeable future. To that end, +maintainers intend to minimize (eliminate if possible) breaking changes post +`v1alpha2`. This GEP is part of that initiative. + +Extension points for match criteria in Routes were added to enable use-cases +where match criteria defined by implementation was a super-set of match +criteria defined within this API. To the best of our knowledge, even though +extension points were added, no concrete examples or use-cases were known at +that time and none have been discovered so far. + +This proposal advocates removal of these extension points because: + +- It goes against the unwritten design principles this API has followed so far: + + - minimize number of API types as much as possible + - minimize strongly coupled API types and instead shoot for self-contained + types. + - extension points are introduced with clear use-cases and possibilities in + mind. Vague extension points are avoided as they become harder to maintain. +- It is unlikely that the user experience resulting from defining two k8s + resources for defining a Route will be optimal. +- There is not prior art on splitting match criteria and backend forwarding + semantics (spec.backends) in the community. We believe they are kept together + for good reasons. + +## API + +The following fields and all associated documentation will be removed: + +- HTTPRouteMatch.ExtensionRef +- TCPRouteMatch.ExtensionRef will be removed. This results in a struct without + any members: TCPRouteMatch. The struct will be kept as it is expected that + more match criteria might be added to L4 routes. + + - Do the same to UDPRoute and TLSRoute + +## Alternatives + +N/A + diff --git a/site-src/ko/geps/gep-820/metadata.yaml b/site-src/ko/geps/gep-820/metadata.yaml new file mode 100644 index 0000000000..8733425669 --- /dev/null +++ b/site-src/ko/geps/gep-820/metadata.yaml @@ -0,0 +1,8 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 820 +name: Drop extension points from Route matches +status: Standard +authors: + - hbagdi + - robscott diff --git a/site-src/ko/geps/gep-851/index.md b/site-src/ko/geps/gep-851/index.md new file mode 100644 index 0000000000..d5ef8ac42e --- /dev/null +++ b/site-src/ko/geps/gep-851/index.md @@ -0,0 +1,79 @@ +# GEP-851: Allow Multiple Certificate Refs per Gateway Listener + +* Issue: [#851](https://github.com/kubernetes-sigs/gateway-api/issues/851) +* Status: Standard + +## TLDR + +Replace `CertificateRef` field with a `CertificateRefs` field in Gateway +Listeners. + +## Goals + +Provide a path for implementations to support: + +* RSA and ECDSA certs on the same Listener. +* Referencing certificates for different hostnames from the same Listener (maybe + as part of a self-service TLS approach). +* Including new and old certificates as part of renewal process. +* Certificate pinning: enable implementations that require certain certificates + for legacy clients while exposing a "normal" certificate to non-legacy + clients. + +## Non-Goals + +* Define how implementations should support these features. Many implementations + have limited control as far as how certs are handled. Some implementations + just pass certs directly to the dataplane and rely on that implementation + specific behavior to determine which certs are used for a given request. That + makes it difficult to define any truly portable handling of multiple + certificates. + +## Introduction + +As described above, there are a number of potential use cases for attaching +multiple certificates to a Gateway Listener. The most straightforward reason for +that involves attaching RSA and ECDSA certs. Although this is not a very common +use case, it is a clearly understood and broadly supported example of why this +change would be helpful. This change will enable implementations to support +these more advanced use cases while still providing a portable core. + +## API + +The `CertificateRef` field in `GatewayTLSConfig` would be replaced with the +following `CertificateRefs` field: + +```go + // CertificateRefs contains a series of references to Kubernetes objects that + // contains TLS certificates and private keys. These certificates are used to + // establish a TLS handshake for requests that match the hostname of the + // associated listener. + // + // A single CertificateRef to a Kubernetes Secret has "Core" support. + // Implementations MAY choose to support attaching multiple certificates to + // a Listener, but this behavior is implementation-specific. + // + // References to a resource in different namespace are invalid UNLESS there + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. If a ReferenceGrant does not allow this reference, the + // "ResolvedRefs" condition MUST be set to False for this listener with the + // "InvalidCertificateRef" reason. + // + // This field is required to have at least one element when the mode is set + // to "Terminate" (default) and is optional otherwise. + // + // CertificateRefs can reference to standard Kubernetes resources, i.e. + // Secret, or implementation-specific custom resources. + // + // Support: Core - A single reference to a Kubernetes Secret + // + // Support: Implementation-specific (More than one reference or other resource types) + // + // +optional + // +kubebuilder:validation:MaxItems=64 + CertificateRefs []*SecretObjectReference `json:"certificateRefs,omitempty"` +``` + +## Alternatives + +N/A diff --git a/site-src/ko/geps/gep-851/metadata.yaml b/site-src/ko/geps/gep-851/metadata.yaml new file mode 100644 index 0000000000..6b85b81849 --- /dev/null +++ b/site-src/ko/geps/gep-851/metadata.yaml @@ -0,0 +1,7 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 851 +name: Allow Multiple Certificate Refs per Gateway Listener +status: Standard +authors: + - robscott diff --git a/site-src/ko/geps/gep-91/index.md b/site-src/ko/geps/gep-91/index.md new file mode 100644 index 0000000000..6fddddb59f --- /dev/null +++ b/site-src/ko/geps/gep-91/index.md @@ -0,0 +1,166 @@ +# GEP-91: Client Certificate Validation for TLS terminating at the Gateway Listener + +* Issue: [#91](https://github.com/kubernetes-sigs/gateway-api/issues/91) +* Status: Implementable + +(See definitions in [GEP States](../overview.md#gep-states).) + +## TLDR + +This GEP proposes a way to validate the TLS certificate presented by the frontend client to the server +(Gateway Listener in this case) during a [TLS Handshake Protocol][]. + +## Goals + +* Define an API field to specify the CA Certificate within the Gateway Listener configuration that can be used as a trust anchor to validate the certificates presented by the client. This use case has been highlighted in the [TLS Configuration GEP][] under segment 1 and in the [Gateway API TLS Use Cases][] document under point 7. + +## Non-Goals +* Define other fields that can be used to verify the client certificate such as the Certificate Hash. + +## Existing support in Implementations + +This feature is widely supported in implementations that support Gateway API. +This table highlights the support. Please feel free to add any missing implementations not mentioned below. + +| Implementation | Support | +|----------------|------------| +| Apache APISIX | [ApisixTls.Client.CASecret](https://apisix.apache.org/docs/ingress-controller/tutorials/mtls/#mutual-authentication) | +| Contour | [HTTPProxy.Spec.VirtualHost.Tls.ClientValidation.CASecret](https://projectcontour.io/docs/v1.17.1/config/tls-termination/) | +| Emissary Ingress| [TlSContext.Spec.Secret](https://www.getambassador.io/docs/emissary/latest/topics/running/tls/mtls) | +| Gloo Edge | [VirtualService.Spec.SSLConfig.SecretRef](https://docs.solo.io/gloo-edge/latest/guides/security/tls/server_tls/#configuring-downstream-mtls-in-a-virtual-service) | +| Istio | [Gateway.Spec.Servers.TLS.Mode](https://istio.io/latest/docs/tasks/traffic-management/ingress/secure-ingress/#configure-a-mutual-tls-ingress-gateway) | +| Kong | [mTLS Plugin](https://docs.konghq.com/hub/kong-inc/mtls-auth/) | +| Traefik | [TLSOption.Spec.ClientAuth](https://doc.traefik.io/traefik/https/tls/#client-authentication-mtls) | +| NGINX Ingress Controller | [ingressMTLS](https://docs.nginx.com/nginx-ingress-controller/configuration/policy-resource/#ingressmtls) | + +### API + +* Introduce a `FrontendValidation` field of type `FrontendTLSValidation` within [GatewayTLSConfig][] that can be used to validate the peer (frontend) with which the TLS connection is being made. +* Introduce a `caCertificateRefs` field within `FrontendTLSValidation` that can be used to specify a list of CA Certificates that can be used as a trust anchor to validate the certificates presented by the client. +* This new field is separate from the existing [BackendTLSPolicy][] configuration. [BackendTLSPolicy][] controls TLS certificate validation for connections *from* the + Gateway to the backend service. This proposal adds the ability to validate the TLS certificate presented by the *client* connecting to the Gateway (the + frontend). These two validation mechanisms operate independently and can be used simultaneously. +* Also introduce a `ObjectReference` structure that can be used to specify `caCertificateRefs` references. + +#### GO + +```go +// ObjectReference identifies an API object including its namespace. +// +// The API object must be valid in the cluster; the Group and Kind must +// be registered in the cluster for this reference to be valid. +// +// References to objects with invalid Group and Kind are not valid, and must +// be rejected by the implementation, with appropriate Conditions set +// on the containing object. +type ObjectReference struct { + // Group is the group of the referent. For example, "gateway.networking.k8s.io". + // When unspecified or empty string, core API group is inferred. + Group Group `json:"group"` + + // Kind is kind of the referent. For example "ConfigMap" or "Service". + Kind Kind `json:"kind"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` + + // Namespace is the namespace of the referenced object. When unspecified, the local + // namespace is inferred. + // + // Note that when a namespace different than the local namespace is specified, + // a ReferenceGrant object is required in the referent namespace to allow that + // namespace's owner to accept the reference. See the ReferenceGrant + // documentation for details. + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` +} + +type GatewayTLSConfig struct { + ...... + // FrontendValidation holds configuration information for validating the frontend (client). + // Setting this field will require clients to send a client certificate + // required for validation during the TLS handshake. In browsers this may result in a dialog appearing + // that requests a user to specify the client certificate. + // The maximum depth of a certificate chain accepted in verification is Implementation specific. + FrontendValidation *FrontendTLSValidation `json:"frontendValidation,omitempty"` +} + +// FrontendTLSValidation holds configuration information that can be used to validate +// the frontend initiating the TLS connection +type FrontendTLSValidation struct { + // CACertificateRefs contains one or more references to + // Kubernetes objects that contain TLS certificates of + // the Certificate Authorities that can be used + // as a trust anchor to validate the certificates presented by the client. + // + // A single CA certificate reference to a Kubernetes ConfigMap + // has "Core" support. + // Implementations MAY choose to support attaching multiple CA certificates to + // a Listener, but this behavior is implementation-specific. + // + // Support: Core - A single reference to a Kubernetes ConfigMap + // with the CA certificate in a key named `ca.crt`. + // + // Support: Implementation-specific (More than one reference, or other kinds + // of resources). + // + // References to a resource in a different namespace are invalid UNLESS there + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. If a ReferenceGrant does not allow this reference, the + // "ResolvedRefs" condition MUST be set to False for this listener with the + // "RefNotPermitted" reason. + // + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:validation:MinItems=1 + CACertificateRefs []ObjectReference `json:"caCertificateRefs,omitempty"` +} + +``` + +#### YAML + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: client-validation-basic +spec: + gatewayClassName: acme-lb + listeners: + - name: foo-https + protocol: HTTPS + port: 443 + hostname: foo.example.com + tls: + certificateRefs: + - kind: Secret + group: "" + name: foo-example-com-cert + frontendValidation: + caCertificateRefs: + - kind: ConfigMap + group: "" + name: foo-example-com-ca-cert +``` + +## Deferred + +This section highlights use cases that may be covered in a future iteration of this GEP + +* Using system CA certificates as the trust anchor to validate the certificates presented by the frontend client. +* Supporting a mode where validating client certificates is optional, useful for debugging and migrating to strict TLS. +* Supporting an optional `subjectAltNames` field within `FrontendTLSValidation` that can be used to specify one or more alternate names to verify the subject identity in the certificate presented by the client. This field falls under Authorization, the initial focus here is on Client Authentication and will be revisited when Authorization is tackled as a whole in the project. +* Specifying the verification depth in the client certificate chain. This is being deferred because the default verification depth differs across implementations. + + +## References + +[TLS Handshake Protocol]: https://www.rfc-editor.org/rfc/rfc5246#section-7.4 +[Certificate Path Validation]: https://www.rfc-editor.org/rfc/rfc5280#section-6 +[GatewayTLSConfig]: /references/spec/#gateway.networking.k8s.io/v1.GatewayTLSConfig +[BackendTLSPolicy]: ../../api-types/backendtlspolicy.md +[TLS Configuration GEP]: ../gep-2907/index.md +[Gateway API TLS Use Cases]: https://docs.google.com/document/d/17sctu2uMJtHmJTGtBi_awGB0YzoCLodtR6rUNmKMCs8/edit?pli=1#heading=h.cxuq8vo8pcxm diff --git a/site-src/ko/geps/gep-91/metadata.yaml b/site-src/ko/geps/gep-91/metadata.yaml new file mode 100644 index 0000000000..409fd393e1 --- /dev/null +++ b/site-src/ko/geps/gep-91/metadata.yaml @@ -0,0 +1,7 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 91 +name: Client Certificate Validation for TLS terminating at the Gateway Listener +status: Provisional +authors: + - arkodg diff --git a/site-src/ko/geps/gep-917/index.md b/site-src/ko/geps/gep-917/index.md new file mode 100644 index 0000000000..0befab81a7 --- /dev/null +++ b/site-src/ko/geps/gep-917/index.md @@ -0,0 +1,211 @@ +# GEP-917: Gateway API Conformance Testing + +* Issue: [#917](https://github.com/kubernetes-sigs/gateway-api/issues/917) +* Status: Memorandum + +## TLDR + +This GEP outlines the principles and overarching structure that Gateway API +conformance tests will be built with. + +## Goals + +- Record why we are doing conformance and what we hope to achieve with it +- Record the success criteria for the conformance process and associated artifacts +- Provide a set of guidelines for conformance test structure + +## Non-Goals + +- Designing the conformance testing framework or implementation +- Designing the process for implementations to prove they are conformant + +## Introduction + +### What is Conformance + +Conformance is the creation of a process that allows everyone, implementors and +users alike, to check that an implementation conforms to the defined spec. + +For core Kubernetes, this also allows for the use of specific badges and branding. + +It usually includes some form of test harness that can produce a standard output, +which can be submitted somewhere for validation. The place where the validations +are held is then the canonical source of information about what implementations +are conformant. + +### Why do it for Gateway API? +The Gateway API is a large, complex API with many use cases and implementations. +Not all implementations support the same features, and some features have +different required support levels. + +One of the primary goals of the Gateway API project is to make it safer and +easier for end users to move their traffic configuration between implementations. +Without some form of conformance to guarantee the same behavior between +implementations, this is simply not achievable. + +Possibly a better way to say this is that we are looking to have Route resources +portable between Gateways with a minimum of spec change. + +By creating a standard set of conformance tests and information, we can: + +- Make it easier for API consumers to understand what a particular API does +- Make it possible for tooling to be constructed to check for portability +between implementations + +Additionally, as the first project to develop an "official" set of CRDs, we have +a responsibility to the community to build out a set of best practices for +similar efforts in the future. Ensuring that whatever we build is reusable for +other projects will help to lift everyone who works with CRDs. + +### What do we need out of conformance for Gateway API? +Must have: + +- Support for only implementing some of the Gateway API CRD resources. Some resources, +like Gateway itself, are required for all implementations, but implementations +may choose what Route resources they support. There will probably be some common +sets of Route resources supported across similar implementations, but this proposal +expects that we will make calls about what to call that common experience at a +later date. +- Support for fields or features that have Core, Extended, and +ImplementationSpecific support. In particular, it must be possible for +implementations to only support some subset of Extended fields, and to be able +to use the framework for their own ImplementationSpecific features if required. +- A testing suite that can validate that an implementation meets the conformance +profiles it claims. +- A way to retrieve conformance information in a machine-parseable way. + +## Proposal + +### Conformance Profiles + +The Gateway API project defines conformance purely in terms of what resources an +implementation supports. +To support a resource, an implementation must support all "Core" functionality +defined by the resource. Support for "Extended" functionality will be indicated +separately. + +All implementations must support all the Core functions on the following resources: + +- GatewayClass +- Gateway +- ReferenceGrant + +The following resources are optional to support, but have defined behavior if you +do: + +- HTTPRoute +- TLSRoute +- TCPRoute +- UDPRoute + +For all of these resources, we should aim to have the usual range of tests for +both the happy and unhappy paths for various types of operations. + +The conformance is versioned - it tracks the required features for a specific +version of the API, and must be included in and updated by a version bump in the +bundle version of the Gateway API. (The _bundle version_ is the thing that we +mark as a "release", that looks like `v0.4.0`, not `v1alpha2`). + +This will enable an implementation to say that it supports a specific version +of the Gateway API. This is again similar to upstream in that implementations need +to submit conformance test results for each version of Kubernetes they support. + +Because the support is defined in terms of the resources that an implementation +supports, the conformance is composable, and orthogonal for each object type. +For example, it's valid to only support HTTPRoute and not TCPRoute, or TLSRoute +and not HTTPRoute. + +### Interaction with existing support levels + +Conformance definitions will ensure that an implementation can provide all the +features currently marked as "Core" support in the API documentation. + +Fields marked "Extended" support will eventually have conformance tests that +lock in the behavior of that feature, and there will be a mechanism for implementations +to tell the testing framework what extended fields they support. + +## Testing framework + +Conformance tests will initially be structured as a CLI that runs on existing +Kubernetes clusters. This may be expanded to include a testing library that can +be imported by implementations. This tool will output test results in a +structured format that can be used to generate reports. Where possible it will +share code with the existing ingress-controller-conformance test suite. + +### Test Definitions + +Each set of tests will be built around a set of YAML manifests representing +Gateway API resources. The tests will focus on how they expect a given +controller to process those resources, configured via GatewayClass name. For +example, tests may check to ensure that a controller correctly populates status, +or that a request is appropriately routed to the desired backend with any +relevant modifications. + +Each test definition will include the following: + +* Name +* Description +* Support Level + +In the future, this will be expanded to include: + +* Docs URL +* Function to determine feature enablement + +### Prepopulated Gateways + +Some implementations of Gateway API support prepopulated or unmanaged `Gateway` +resources that refer to an underlying server that was created by other means +(e.g. `Helm`) rather than provisioning and managing the server according to the +`Gateway` resource. To ensure that our conformance tests can adequately cover +these implementations, Gateways and any accompanying infrastructure may be +preloaded into the cluster in which conformance tests will run. Importantly, +Routes, ReferencePolicies, Services, or other resources used by the test MUST +NOT be prepopulated. This approach will require a `--prepopulated-gateways` flag +to be set, this will also be represented in the resulting conformance report. + +## Certification process + +The Gateway API project will provide a process by which an implementation may +submit the results of a run of the conformance test suite to a centralized, +open repository, and once verified, these results will be used to maintain a +canonical list of certified conformant implementations. + +Ideally, this process should be handled using similar methods to upstream +Kubernetes, while also learning what we can from what the upstream conformance +efforts wish they could improve. + +## Alternatives Considered + +### Tests Derived from Gateways + +It could be possible to write a testing framework that could derive the tests +to run from Gateways that were present in a given cluster. For example, if a +Gateway was present with an HTTP listener, it would run all tests that were +possible with that type of listener. + +This approach could be especially helpful for implementations that do not yet +support provisioning arbitrary Gateways. With the current proposal, these +implementations would have to prepopulate a predefined set of Gateways for +testing. + +Unfortunately, this approach also comes with some significant downsides: + +1. Implementations would still have to prepopulate Gateways. +1. There are many possible inputs and outputs. +1. We would need to test the testing framework to ensure that the correct tests + were being run with a given input. +1. The testing framework logic could become complicated if we wanted to avoid + repeating tests that had already been run with other listeners. +1. It may be more difficult to debug these tests if anything went wrong. +1. Tests would need to be smart enough to recognize the side effects of any + tests that had previously run. For example, multiple tests using the same + Gateway could result in different status conditions depending on the order + and/or combination that ran. + + +## References + +* [Gateway API Conformance Ideas](https://docs.google.com/document/d/18iECeKMp1OewSGISskv6Chfmjo9u2U0_iUH0jhPdKOk/edit#) +* [Gateway API Conformance Requirements](https://docs.google.com/document/d/1QL-MpIVzqxe32Y2BZ_dYOB8zNsF9c4pnKEIB9ZLt118/edit) +* [Gateway API Conformance Details](https://docs.google.com/document/d/1QL-MpIVzqxe32Y2BZ_dYOB8zNsF9c4pnKEIB9ZLt118/edit) diff --git a/site-src/ko/geps/gep-917/metadata.yaml b/site-src/ko/geps/gep-917/metadata.yaml new file mode 100644 index 0000000000..48fc2c05e0 --- /dev/null +++ b/site-src/ko/geps/gep-917/metadata.yaml @@ -0,0 +1,8 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 917 +name: Gateway API Conformance Testing +status: Memorandum +authors: + - youngnick + - robscott diff --git a/site-src/ko/geps/gep-922/index.md b/site-src/ko/geps/gep-922/index.md new file mode 100644 index 0000000000..1d0ffa6f24 --- /dev/null +++ b/site-src/ko/geps/gep-922/index.md @@ -0,0 +1,183 @@ +# GEP-922: Gateway API Versioning + +* Issue: [#922](https://github.com/kubernetes-sigs/gateway-api/issues/922) +* Status: Memorandum + +!!! note + Although this GEP serves as a reference for how we developed the Gateway API + versioning model, it is not meant to be the current source of truth. + Instead, please refer to our [official Versioning + Policy](../../concepts/versioning.md) for the most up-to-date guidelines. + +## TLDR +Each Gateway API release will be represented by a bundle version that represents +that specific combination of CRDs, API versions, and validating webhook. To +enable experimental fields, future releases of the API will include standard and +experimental CRD tracks. Users will be able to access experimental features by +installing the experimental CRDs. A cluster can contain either an experimental +or standard CRD for any resource at a given time. + +## Goals +Provide a path for implementations to support: + +* Users should have a predictable experience when interacting with Gateway API. +* The API should be able to continue to safely evolve, including: + * Loosening validation + * Transitioning required fields to optional + * Adding new fields at an experimental stability level + +## Introduction +This GEP details how we should approach future releases of Gateway API. This is +intended as another step towards building consensus. Once merged, it will be +considered implemented once this content is fully documented. + +## Version Terminology +Gateway API has two related but different versioning schemes: + +### 1. API Versions (ex: v1alpha2) +Each API version provides a unique way to interact with the API. Significant +changes such as removing or renaming fields will be represented here. + +### 2. Bundle Versions (ex: v0.4.0) +Bundle versions are broader in scope. They use semantic versioning and include +the following: + +* API Types/CRDs +* Validating Webhook + +Each bundle may include multiple API versions, potentially introducing new ones +and/or removing old ones as part of a new bundle. + +## Limitations of Webhook and CRD Validation +CRD and webhook validation is not the final validation i.e. webhook is “nice UX” +but not schema enforcement. This validation is intended to provide immediate +feedback to users when they provide an invalid configuration, but cannot +completely be relied on because it: + +* Is not guaranteed to be present or up to date in all clusters. +* Will likely never be sufficient to cover all edge cases. +* May be loosened in future API releases. + +## Persona Requirements +When implementing or using Gateway API, each persona has a unique set of +responsibilities to ensure we're providing a consistent experience. + +### API Authors: +* MUST provide conversion between API versions (excluding experimental fields), + starting with v1alpha2. +* MAY include the following changes to an existing API version with a new bundle + **patch** version: + * Clarifications to godocs + * Updates to CRDs and/or code to fix a bug + * Fixes to typos +* MAY include the following changes to an existing API version with a new bundle + **minor** version: + * Everything that is valid in a patch release + * New experimental API fields or resources + * Loosened validation + * Making required fields optional + * Removal of experimental fields + * Removal of experimental resources + * Graduation of fields or resources from experimental to standard track +* MAY introduce a new **API version** with a new bundle minor version, which may + include: + * Everything that is valid in a minor release + * Renamed fields + * Anything else that is valid in a new Kubernetes API version + * Removal/tombstoning of beta fields +* MAY release a new major bundle version (v1.0) as part of graduating the API to + GA and releasing a new API version. + +Note that each new bundle version, no matter how small, may include updated +CRDs, webhook, or both. Implementations may read annotations on Gateway API CRDs +(defined below) to determine the version and channel of CRDs that have been +installed in the cluster. + +### Implementers: +* MUST handle fields with loosened validation without crashing +* MUST handle fields that have transitioned from required to optional without + crashing +* MUST NOT rely on webhook or CRD validation as a security mechanism. If field + values need to be escaped to secure an implementation, both webhook and CRD + validation can be bypassed and cannot be relied on. Instead, implementations + should implement their own escaping or validation as necessary. To avoid + duplicating work, Gateway API maintainers are considering adding a shared + validation package that implementations can use for this purpose. This is + tracked by [#926](https://github.com/kubernetes-sigs/gateway-api/issues/926). + +### Installers: +* MUST install a full Gateway API bundle, with matching CRD and webhook + versions. + +## Adding Experimental Fields +Over time, it will be useful to add experimental fields to the API. In upstream +Kubernetes, those would generally be guarded with feature gates. With Gateway +API we will accomplish by releasing experimental versions of our CRDs. + +With this approach, we achieve a similar result. Instead of using feature gates +and validation to prevent fields from being set, we just release separate CRDs. +Once the API reaches beta, each bundle release can include 2 sets of CRDs, +standard and experimental. + +New fields will be added to the experimental set of CRDs first, and may graduate +to the standard set of APIs later. Experimental fields will be marked with the +`+experimental` annotation in Go type definitions. Gateway API CRD generation +will exclude these fields from standard set of CRDs. Experimental fields may be +removed from the API. Due to the experimental nature of these CRDs, they are not +recommended for production use. + +If experimental fields are removed or renamed, the original field name should be +removed from the go struct, with a tombstone comment ensuring the field name +will not be reused. + +Each CRD will be published with annotations that indicate their bundle version +and channel: + +``` +gateway.networking.k8s.io/bundle-version: v0.4.0 +gateway.networking.k8s.io/channel: standard|experimental +``` + +## Alternatives Considered +### 1. Use Webhook to Implement Feature Gates +This option would involve using the webhook to prevent experimental fields from +being set unless the corresponding feature gate was enabled. This would make use +of the existing Kubernetes feature gate tooling. + +This approach would be familiar to Kubernetes users, but would put a lot of +emphasis on the webhook. It would require webhook versioning to be precisely in +line with the CRDs, and edge cases during the upgrade process could get rather +messy. + +### 2: Reuse Alpha API versions +With this approach, we would only allow the use of these fields when using the +alpha API. + +To simplify conversion, new fields will be added to all versions of the API, +with some key exceptions: + +* New fields will be added with an `alpha` prefix to beta and GA API versions. +* Webhook validation would ensure that new fields will only be writable when + using alpha API versions. +* New fields may be removed without replacement while they are still considered + alpha. + +An alpha API field could graduate to beta in the subsequent minor release of the +API. That process would involve: + +* Loosening webhook validation to allow writes to the field with beta API + versions. +* Removing the alpha prefix from the field name in the beta API Changing the + alpha prefix to a beta prefix in the GA API. + +A beta API field could graduate to GA in the subsequent minor release of the +API. That process would involve: + +* Loosening webhook validation to allow writes to the field with GA API + versions. +* Removing the beta prefix from the field name in the GA API. + +This is potentially the most complex of all the options presented. It would +effectively require us to consistently maintain an alpha API version. Of all the +options presented, this is probably the most likely to confuse users and +implementers of the API. diff --git a/site-src/ko/geps/gep-922/metadata.yaml b/site-src/ko/geps/gep-922/metadata.yaml new file mode 100644 index 0000000000..423747909e --- /dev/null +++ b/site-src/ko/geps/gep-922/metadata.yaml @@ -0,0 +1,7 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 922 +name: Gateway API Versioning +status: Memorandum +authors: + - robscott diff --git a/site-src/ko/geps/gep-957/index.md b/site-src/ko/geps/gep-957/index.md new file mode 100644 index 0000000000..d2f3ead5af --- /dev/null +++ b/site-src/ko/geps/gep-957/index.md @@ -0,0 +1,138 @@ +# GEP-957: Destination Port Matching + +* Issue: [#957](https://github.com/kubernetes-sigs/gateway-api/issues/957) +* Status: Standard + +## TLDR + +Add a new `port` field to ParentRef to support port matching in Routes. + +## Goals + +* Support port matching in routes based on the destination port number of the + request. + +## Non-Goals + +* Support port matching based on port name. + +## Introduction + +Port matching is a common service mesh use case where traffic policies/rules +need to be applied to traffic to certain destination ports. For ingress, while +the API today already supports attaching a route to a specific listener, it may +be useful to support attaching routes to listener(s) on a specified port. This +allows route authors to apply networking behaviors on a fixed port. + +## API + +The proposal is to add a new field `Port` to `ParentRef`: + +```go +type ParentRef struct { + ... + // Port is the network port this Route targets. It can be interpreted + // differently based on the type of parent resource: + // + // Gateway: All listeners listening on the specified port that also support + // this kind of Route(and select this Route). It's not recommended to set + // `Port` unless the networking behaviors specified in a Route must + // apply to a specific port as opposed to a listener(s) whose port(s) may + // be changed. + // When both Port and SectionName are specified, the name and port of the + // selected listener must match both specified values. + // + // Implementations MAY choose to support other parent resources. + // Implementations supporting other types of parent resources MUST clearly + // document how/if Port is interpreted. + // + // For the purpose of status, an attachment is considered successful as + // long as the parent resource accepts it partially. For example, Gateway + // listeners can restrict which Routes can attach to them by Route kind, + // namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + // the referencing Route, the Route MUST be considered successfully + // attached. If no Gateway listeners accept attachment from this Route, the + // Route MUST be considered detached from the Gateway. + // + // Support: Core + // + // +optional + Port *PortNumber `json:"port,omitempty"` + ... +} +``` + +The following example shows how an HTTPRoute could be applied to port 8000. In +this example, the HTTPRoute will be attached to listeners foo and bar on port +8000 but not listener baz on port 8080. +```yaml +kind: HTTPRoute +metadata: + name: example + namespace: example +spec: + parentRef: + - name: my-gateway + port: 8000 + ... +--- +kind: Gateway +metadata: + name: my-gateway + namespace: example +spec: + listeners: + - name: foo + port: 8000 + protocol: HTTP + ... + - name: bar + port: 8000 + protocol: HTTP + ... + - name: baz + port: 8080 + ... +``` + +The following example shows how a TCPRoute could be attached to an Mesh CRD to +route all traffic in a service mesh whose original destination port is 8000 to +port 8080 of service foo. +```yaml +kind: TCPRoute +metadata: + name: example + namespace: example +spec: + parentRef: + - name: my-mesh + group: example.io + kind: Mesh + port: 8000 + rules: + - backendRefs + - name: foo + port: 8080 +``` + +## Alternatives +### 1. Use SectionName in ParentRef for port matching +Port matching can be supported if SectionName accepts port numbers in addition +to listener names. This approach results in a less explicit API when a ParentRef +points to a resource that is not `Gateway`. For example, an implementation may +attach a route to an `Mesh` CRD. In this case, it's less intuitive to set +`ParentRef.SectionName` to `443` to express `route all traffic whose destination +port is 443 to ...`. It also complicates the validation on SectionName in order +to differentiate between a listener name and a port number. + +### 2. Update TrafficMatches to support port matching +TrafficMatches was proposed in +[gep-735](../gep-735/index.md) to support TCP and UDP +address matching. TrafficMatches can be extended to support port matching. +TrafficMatches will need to be added to HTTPRoute/TLSRoute if the feature is +desired there. + +While this proposal works for mesh, it may be confusing for ingress because a +user can specify port matching behavior in a route that is incompatible with +the listeners the route attaches to. For example, a user can specify a match +on port 443 in a route while the route only attaches to a listener on port 80. diff --git a/site-src/ko/geps/gep-957/metadata.yaml b/site-src/ko/geps/gep-957/metadata.yaml new file mode 100644 index 0000000000..610f1f66e0 --- /dev/null +++ b/site-src/ko/geps/gep-957/metadata.yaml @@ -0,0 +1,10 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 957 +name: Destination Port Matching +status: Standard +authors: + - cxhiano + - robscott + - shaneutt + diff --git a/site-src/ko/geps/gep-995/index.md b/site-src/ko/geps/gep-995/index.md new file mode 100644 index 0000000000..6236d1a279 --- /dev/null +++ b/site-src/ko/geps/gep-995/index.md @@ -0,0 +1,81 @@ +# GEP-995: Named route rules + +* Issue: [#995](https://github.com/kubernetes-sigs/gateway-api/issues/995) +* Status: Experimental + +## TLDR + +Add a new optional `name` field to the route rule types ([GRPCRouteRule](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.GRPCRouteRule), [HTTPRouteRule](../../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteRule), [TCPRouteRule](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.TCPRouteRule), [TLSRouteRule](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.TLSRouteRule) and [UDPRouteRule](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.UDPRouteRule)) to support referencing individual rules by name. + +## Goals + +* Support referencing individual route rules by name from other resources, such as from metaresources ([GEP-2648](../gep-2648/index.md#apply-policies-to-sections-of-a-resource).) +* Support referencing individual route rules by name from condition messages propagated in the status stanza of route resources as suggested in https://github.com/kubernetes-sigs/gateway-api/issues/1696#issuecomment-1666258188. +* Support referencing individual route rules by name at other observability and networking tools that are part of the ecosystem based on Gateway API. +* Provide a rather intuitive API for users of Kubernetes who are familiar with the same pattern employed already by other kinds of resources where lists of complex elements can be declared – e.g. service [ports](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec), pod [containers](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#containers) and pod [volumes](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#volumes). +* Provide a guide to the implementations about the expected behavior in cases where the name of the route rule is missing (empty value or `nil`.) + +## Non-Goals + +* Mandate the `name` field to be a require field. +* Limit the usage of the route rule name value for the implementations, such as exclusively for the `targetRef` section of policies (metaresources.) +* Define a patch strategy for the route objects based on rule `name`. + +## Introduction + +Some kinds of Gateway API types are complex types that support specifying lists of yet other complex object details within them. Examples include the [`GatewaySpec`](../../reference/spec.md#gateway.networking.k8s.io/v1.GatewaySpec) type, the [`HTTPRouteSpec`](../../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteSpec) type, as well as other kinds of route specification types. Specifically, `Gateway` objects can declare multiple complex listener details (`spec.listeners`); similarly, `HTTPRoute` objects may contain multiple complex routing rule details (`spec.rules`). + +Even with a limited number of elements declared within those lists of resource specification details, without a field that works as a unique identifier of each element (e.g., a `name` field), referring individual ones can often lead to implementations that are inconsistent, complex, and error-prone. This is an issue for any kind of referencing pattern, including for Policy Attachment, status reporting, event logging, etc. + +Referencing list elements without a unique identifier is also prone to execution errors, either when relying on how the elements are sorted in the list (i.e., based on the index) or on partial or total repetition of values of the referents. The order of elements within a list may change without necessarily any semantic reason. Complex elements can sometimes differ only subtly from each other, thus easily being overlooked when making the reference and resulting in a higher chance of typos and/or references that are possibly ambiguous or broken. In both cases, such references are fragile and can result in unexpected errors. + +For the `Gateway` resource, problems above were addressed/mitigated by adding a `name` field to the [`Listener`](../../reference/spec.md#gateway.networking.k8s.io/v1.Listener) type ([#724](https://github.com/kubernetes-sigs/gateway-api/issues/).) Listener names are required and must be unique of each listener declared in a gateway. This allowed for more explicit route and policy attachment relying on _sectionName_, as well as it opened for better implementation of status reporting and log recording of events related to specific gateway listeners. + +In general, declaring explicit names for complex list elements is a common pattern in Kubernetes, observed in several other APIs. Examples include [containers](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#containers) and [volumes](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#volumes) of a Pod, [ports](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec) of a Service, and many others. + +This GEP aims to rollout the same pattern of declarative `name` fields of these examples to the Gateway API route rule types. + +## API + +This GEP proposes to add a new optional `name` field to the [GRPCRouteRule](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.GRPCRouteRule), [HTTPRouteRule](../../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteRule), [TCPRouteRule](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.TCPRouteRule), [TLSRouteRule](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.TLSRouteRule) and [UDPRouteRule](../../reference/spec.md#gateway.networking.k8s.io/v1alpha2.UDPRouteRule) types. + +### Format + +If specified, the name of a route rule MUST comply with the [`SectionName`](https://github.com/kubernetes-sigs/gateway-api/blob/v1.0.0/apis/v1/shared_types.go#L607-L624) type: +- starts and ends with a lower case Latin letter (`a-z`) or digit (`0-9`); +- accepts any lower case Latin letter (`a-z`), digits (`0-9`), and the following special characters: `-`, `.`; +- contains a minimum of 1 and maximum of 253 characters. + +### Volition + +To preserve backward compatibility with previous version of the affected APIs, the `name` field for route rules should be introduced in the API as optional – i.e., end-user are not forced to add it to their existing or new route objects. + +Implementations MAY recommend the usage of the `name` field for enabling specific features, such as for supporting policy attachment targeting individual route rules, and more assertive log messages and/or status reporting that include on the name of the rule. However, because as by API design the presence of the field is optional, implementations MUST take into account that a value may sometimes not be available. For such cases, implementations are free to decide whether to provide the feature depending the `name` field, if the feature is not required for Core compliance, or to enable the feature relying on another method of referencing of choice. + +### Default value + +Implementations MUST NOT assume a default value for the `name` field for route rules when not specified by the end-user. + +Please refer to the [Volition](#volition) subsection for alternatives if `name` field is missing. + +### Mutability + +Implementations MAY prevent end-users from updating the name of a route rule. If updates are allowed the semantics and behaviour will depend on the underlying implementation. + +## Alternatives + +### Reference route rules by index +- Consistency can be easily broken by adding/removing new rules +- Less descriptive compared to a name + +### Reference route rules by matching field values of rule +- Complexity associated with the API types of the referent bubbles up to the level of the reference +- Consistency can be easily broken due to duplication of values between reference and referent +- Does not solve for easy referencing in debugging, logging, status messages – i.e. some verbosity required to communicate what route rule the events refers to + +### Break down route objects into smaller ones (with less rules) +- Could lead to an explosion of route objects containing a single rule each, thus defeating the purpose of supporting lists of rules within route objects in the first place – though large routes with many rules are also generally discouraged (https://github.com/kubernetes-sigs/gateway-api/issues/1696#issuecomment-1679804122) + +### Use filters to extend behavior of specific route rules +- Does not solve for easy referencing in debugging, logging, status messages – i.e. some verbosity required to communicate what route rule the events refers to +- No support for third-parties diff --git a/site-src/ko/geps/gep-995/metadata.yaml b/site-src/ko/geps/gep-995/metadata.yaml new file mode 100644 index 0000000000..547d7bfdfa --- /dev/null +++ b/site-src/ko/geps/gep-995/metadata.yaml @@ -0,0 +1,19 @@ +apiVersion: internal.gateway.networking.k8s.io/v1alpha1 +kind: GEPDetails +number: 995 +name: Named route rules +status: Experimental +authors: + - guicassolato +changelog: + - "https://github.com/kubernetes-sigs/gateway-api/pull/2593" +relationships: + seeAlso: + - number: 2648 + name: Direct Policy Attachment + description: Defines a way to attach direct policies to sections of a route. + - number: 2649 + name: Inherited Policy Attachment + description: | + Provides a more assertive way to report status regarding sections of a route. + E.g.: when a policy that targets a Service affects rules of a route. diff --git a/site-src/ko/geps/overview.md b/site-src/ko/geps/overview.md new file mode 100644 index 0000000000..808cdb0a80 --- /dev/null +++ b/site-src/ko/geps/overview.md @@ -0,0 +1,264 @@ +# Gateway Enhancement Proposal (GEP) + +Gateway Enhancement Proposals (GEPs) serve a similar purpose to the [KEP][kep] +process for the main Kubernetes project: + +1. Ensure that changes to the API follow a known process and discussion + in the OSS community. +1. Make changes and proposals discoverable (current and future). +1. Document design ideas, tradeoffs, decisions that were made for + historical reference. +1. Record the results of larger community discussions. +1. Record changes to the GEP process itself. + +## Process + +This diagram shows the state diagram of the GEP process at a high level, but the details are below. + +
+ +```mermaid +flowchart TD + D([Discuss with
the community]) --> C + C([Issue Created]) -------> Memorandum + C([Issue Created]) --> Provisional + Provisional -->|If practical
work needed| Prototyping + Provisional -->|GEP Doc PR
done| Implementable + Prototyping -->|GEP Doc PR
done| Implementable + Implementable -->|Gateway API
work completed| Experimental + Experimental -->|Supported in
multiple implementations
+ Conformance tests| Standard + Standard -->|Entire change is GA or implemented| Completed + +``` + +
+ +## GEP Definitions + +### GEP States + +Each GEP has a state, which tracks where it is in the GEP process. + +GEPs can move to some states from any other state: + + * **Deferred:** We do not currently have bandwidth to handle this GEP, it + may be revisited in the future. + * **Declined:** This proposal was considered by the community but ultimately + rejected and further work will not occur. + * **Withdrawn:** This proposal was considered by the community but ultimately + withdrawn by the author. + +There is a special state to cover Memorandum GEPs: + + * **Memorandum**: These GEPs either: + * Document an agreement for further work, creating no spec changes themselves, or + * Update the GEP process. + +API GEPs flow through a number of states, which generally correspond to the level +of stability of the change described in the GEP: + + * **Provisional:** The goals described by this GEP have consensus but + implementation details have not been agreed to yet. + * **Prototyping:** An optional extension of `Provisional` in + order to indicate to the community that there are some active practical tests + and experiments going on which are intended to be a part of the development + of this GEP. This may include APIs or code, but that content _must_ not be + distributed with releases. + * **Implementable:** The goals and implementation details described by this GEP + have consensus but have not been fully implemented yet. + * **Experimental:** This GEP has been implemented and is part of the + "Experimental" release channel. Breaking changes are still possible, up to + and including complete removal and moving to `Rejected`. + * **Standard:** This GEP has been implemented and is part of the + "Standard" release channel. It should be quite stable. + * **Completed**: All implementation work on this API GEP has been completed. + +### Relationships between GEPs + +GEPs can have relationships between them. At this time, there are three possible +relationships: + +* **Obsoletes** and its backreference **ObsoletedBy**: when a GEP is made obsolete + by another GEP, and has its functionality completely replaced. The Obsoleted + GEP is moved to the **Declined** state. +* **Extends** and its backreference **ExtendedBy**: when a GEP has additional details + or implementation added in another GEP. +* **SeeAlso**: when a GEP is relevant to another GEP, but is not affected in any + other defined way. + +Relationships are tracked in the YAML metadata files accompanying each GEP. + +### GEP metadata file + +Each GEP has a YAML file containing metadata alongside it, please keep it up to +date as changes to the GEP occur. + +In particular, note the `authors`, and `changelog` fields, please keep those up +to date. + +## Process + +### 1. Discuss with the community + +Before creating a GEP, share your high level idea with the community. There are +several places this may be done: + +- A [new GitHub Discussion](https://github.com/kubernetes-sigs/gateway-api/discussions/new) +- On our [Slack Channel](https://kubernetes.slack.com/archives/CR0H13KGA) +- On one of our [community meetings](../contributing/index.md?h=meetings#meetings) + +Please default to GitHub discussions: they work a lot like GitHub issues which +makes them easy to search. + +### 2. Create an Issue +[Create a GEP issue](https://github.com/kubernetes-sigs/gateway-api/issues/new?assignees=&labels=kind%2Ffeature&template=enhancement.md) in the repo describing your change. +At this point, you should copy the outcome of any other conversations or documents +into this document. + +### 3. Agree on the Goals +Although it can be tempting to start writing out all the details of your +proposal, it's important to first ensure we all agree on the goals. + +For API GEPs, the first version of your GEP should aim for a "Provisional" +status and leave out any implementation details, focusing primarily on +"Goals" and "Non-Goals". + +For Memorandum GEPs, the first version of your GEP will be the only one, as +Memorandums have only a single stage - `Accepted`. + +### 3. Document Implementation Details +Now that everyone agrees on the goals, it is time to start writing out your +proposed implementation details. These implementation details should be very +thorough, including the proposed API spec, and covering any relevant edge cases. +Note that it may be helpful to use a shared doc for part of this phase to enable +faster iteration on potential designs. + +It is likely that throughout this process, you will discuss a variety of +alternatives. Be sure to document all of these in the GEP, and why we decided +against them. At this stage, the GEP should be targeting the "Implementable" +stage. + +### 4. Implement the GEP as "Experimental" + +With the GEP marked as "Implementable", it is time to actually make those +proposed changes in our API. In some cases, these changes will be documentation +only, but in most cases, some API changes will also be required. It is important +that every new feature of the API is marked as "Experimental" when it is +introduced. Within the API, we use `` tags to denote +experimental fields. Within Golang packages (conformance tests, CLIs, e.t.c.) we +use the `experimental` Golang build tag to denote experimental functionality. + +Some other requirements must be met before marking a GEP `Experimental`: + +- the graduation criteria to reach `Standard` MUST be filled out +- a proposed probationary period (see next section) must be included in the GEP + and approved by maintainers. + +Before changes are released they MUST be documented. GEPs that have not been +both implemented and documented before a release cut off will be excluded from +the release. + +#### Probationary Period + +Any GEP in the `Experimental` phase is automatically under a "probationary +period" where it will come up for re-assessment if its graduation criteria are +not met within a given time period. GEPs that wish to move into `Experimental` +status MUST document a proposed period (6 months is the suggested default) that +MUST be approved by maintainers. Maintainers MAY select an alternative time +duration for a probationary period if deemed appropriate, and will document +their reasoning. + +> **Rationale**: This probationary period exists to avoid GEPs getting "stale" +> and to provide guidance to implementations about how relevant features should +> be used, given that they are not guaranteed to become supported. + +At the end of a probationary period if the GEP has not been able to resolve +its graduation criteria it will move to "Rejected" status. In extenuating +circumstances an extension of that period may be accepted by approval from +maintainers. GEPs which are `Rejected` in this way are removed from the +experimental CRDs and more or less put on hold. GEPs may be allowed to move back +into `Experimental` status from `Rejected` for another probationary period if a +new strategy for achieving their graduation criteria can be established. Any +such plan to take a GEP "off the shelf" must be reviewed and accepted by the +maintainers. + +> **Warning**: It is extremely important** that projects which implement +> `Experimental` features clearly document that these features may be removed in +> future releases. + +### 5. Graduate the GEP to "Standard" + +Once this feature has met the [graduation criteria](../concepts/versioning.md#graduation-criteria), it is +time to graduate it to the "Standard" channel of the API. Depending on the feature, this may include +any of the following: + +1. Graduating the resource to beta +2. Graduating fields to "standard" by removing `` tags +3. Graduating a concept to "standard" by updating documentation + +### 6. Close out the GEP issue + +The GEP issue should only be closed once the feature has: +- Moved to the standard channel for distribution (if necessary) +- Moved to a "v1" `apiVersion` for CRDs +- been completely implemented and has wide acceptance (for process changes). + +In short, the GEP issue should only be closed when the work is "done" (whatever +that means for that GEP). + +## Format + +GEPs should match the format of the template found in [GEP-696](gep-696/index.md). + +## Out of scope + +What is out of scope: see [text from KEP][kep-when-to-use]. Examples: + +* Bug fixes +* Small changes (API validation, documentation, fixups). It is always + possible that the reviewers will determine a "small" change ends up + requiring a GEP. + +## FAQ + +#### Why is it named GEP? +To avoid potential confusion if people start following the cross references to +the full KEP process. + +#### Why have a different process than mainline? +Gateway API has some differences with most upstream KEPs. Notably Gateway API +intentionally avoids including any implementation with the project, so this +process is focused entirely on the substance of the API. As this project is +based on CRDs it also has an entirely separately release process, and has +developed concepts like "release channels" that do not exist in upstream. + +#### Is it ok to discuss using shared docs, scratch docs etc? +Yes, this can be a helpful intermediate step when iterating on design details. +It is important that all major feedback, discussions, and alternatives +considered in that step are represented in the GEP though. A key goal of GEPs is +to show why we made a decision and which alternatives were considered. If +separate docs are used, it's important that we can still see all relevant +context and decisions in the final GEP. + +#### When should I mark a GEP as `Prototyping` as opposed to `Provisional`? +The `Prototyping` status carries the same base meaning as `Provisional` in that +consensus is not complete between stakeholders and we're not ready to move +toward releasing content yet. You should use `Prototyping` to indicate to your +fellow community members that we're in a state of active practical tests and +experiments which are intended to help us learn and iterate on the GEP. These +can include distributing content, but not under any release channel. + +#### Should I implement support for `Experimental` channel features? +Ultimately one of the main ways to get something into `Standard` is for it to +mature through the `Experimental` phase, so we really _need_ people to implement +these features and provide feedback in order to have progress. That said, the +graduation of a feature past `Experimental` is not a forgone conclusion. Before +implementing an experimental feature, you should: + +* Clearly document that support for the feature is experimental and may + disappear in the future. +* Have a plan in place for how you would handle the removal of this feature from + the API. + +[kep]: https://github.com/kubernetes/enhancements +[kep-when-to-use]: https://github.com/kubernetes/enhancements/tree/master/keps#do-i-have-to-use-the-kep-process diff --git a/site-src/ko/guides/api-design.md b/site-src/ko/guides/api-design.md new file mode 100644 index 0000000000..224e51d37e --- /dev/null +++ b/site-src/ko/guides/api-design.md @@ -0,0 +1,148 @@ +# API Design Guide + +There are some general design guidelines used throughout this API. + +!!! note + Throughout the Gateway API documentation and specification, + keywords such as "MUST", "MAY", and "SHOULD" are used + broadly. These should be interpreted as described in RFC 2119. + +## Single resource consistency + +The Kubernetes API guarantees consistency only on a single resource level. There +are a couple of consequences for complex resource graphs as opposed to single +resources: + +* Error checking of properties spanning multiple resource will be asynchronous + and eventually consistent. Simple syntax checks will be possible at the + single resource level, but cross resource dependencies will need to be + handled by the controller. +* Controllers will need to handle broken links between resources and/or + mismatched configuration. + +## Conflicts + +Separation and delegation of responsibility among independent actors (e.g +between cluster ops and application developers) can result in conflicts in the +configuration. For example, two application teams may inadvertently submit +configuration for the same HTTP path. + +In most cases, guidance for conflict resolution is provided along with the +documentation for fields that may have a conflict. If a conflict does not have a +prescribed resolution, the following guiding principles should be applied: + +* Prefer not to break things that are working. +* Drop as little traffic as possible. +* Provide a consistent experience when conflicts occur. +* Make it clear which path has been chosen when a conflict has been identified. + Where possible, this should be communicated by setting appropriate status + conditions on relevant resources. +* More specific matches should be given precedence over less specific ones. +* The resource with the oldest creation timestamp wins. +* If everything else is equivalent (including creation timestamp), precedences + should be given to the resource appearing first in alphabetical order + (namespace/name). For example, foo/bar would be given precedence over foo/baz. + +## Gracefully Handling Future API Versions + +An important consideration when implementing this API is how it might change in +the future. Similar to the Ingress API before it, this API is designed to be +implemented by a variety of different products within the same cluster. That +means that the API version your implementation was developed with may be +different than the API version it is used with. + +At a minimum, the following requirements must be met to ensure future versions +of the API do not break your implementation: + +* Handle fields with loosened validation without crashing +* Handle fields that have transitioned from required to optional without + crashing + +### Supported API Versions + +The version of Gateway API CRDs that is installed in a cluster can be determined +by looking at the `gateway.networking.k8s.io/bundle-version` annotation on each +CRD. Each implementation MUST compare that with the list of versions that it +recognizes and supports. Implementations with a GatewayClass MUST publish the +`SupportedVersion` condition on the GatewayClass to indicate whether the CRDs +installed in the cluster are supported. + +## Limitations of CRD and Webhook Validation + +??? note "Webhook Validation is Deprecated" + + Webhook validation in Gateway API has been deprecated and was fully + removed in v1.1.0. With that said, all of this guidance will still apply for + implementations as long as they support v1.0.0 or older releases of the API. + +CRD and webhook validation is not the final validation i.e. webhook is "nice UX" +but not schema enforcement. This validation is intended to provide immediate +feedback to users when they provide an invalid configuration. Write code +defensively with the assumption that at least some invalid input (Gateway API +resources) will reach your controller. Both Webhook and CRD validation is not +fully reliable because it: + +* May not be deployed correctly. +* May be loosened in future API releases. (Fields may contain values with less + restrictive validation in newer versions of the API). + +*Note: These limitations are not unique to Gateway API and apply more broadly to +any Kubernetes CRDs and webhooks.* + +Implementers should ensure that, even if unexpected values are encountered in +the API, their implementations are still as secure as possible and handle this +input gracefully. The most common response would be to reject the configuration +as malformed and signal the user via a condition in the status block. To avoid +duplicating work, Gateway API maintainers are considering adding a shared +validation package that implementations can use for this purpose. This is +tracked by [#926](https://github.com/kubernetes-sigs/gateway-api/issues/926). + +### Expectations + +We expect there will be varying levels of conformance among the +different providers in the early days of this API. Users can use the +results of the conformance tests to understand areas where there may +be differences in behavior from the spec. + +### Implementation-specific + +In some aspects of the API, we give the user an ability to specify usage of the +feature, however, the exact behavior may depend on the underlying +implementation. For example, regular expression matching is present in all +implementations but specifying an exact behavior is impossible due to +subtle differences between the underlying libraries used (e.g. PCRE, ECMA, +Re2). It is still useful for our users to spec out the feature as much as +possible, but we acknowledge that the behavior for some subset of the API may +still vary (and that's ok). + +These cases will be specified as defining delimited parts of the API +"implementation-specific". + + +## Kind vs. Resource + +Similar to other Kubernetes APIs, Gateway API uses "Kind" instead of "Resource" +in object references throughout the API. This pattern should be familiar to +most Kubernetes users. + +Per the [Kubernetes API conventions][1], this means that all implementations of +this API should have a predefined mapping between kinds and resources. Relying +on dynamic resource mapping is not safe. + +## API Conventions + +Gateway API follows Kubernetes API [conventions][1]. These conventions +are intended to ease client development and ensure that configuration +mechanisms can consistently be implemented across a diverse set of use +cases. In addition to the Kubernetes API conventions, Gateway API has the +following conventions: + +### List Names + +Another convention this project uses is for plural field names for lists +in our CRDs. We use the following rules: + +- If the field name is a noun, use a plural value. +- If the field name is a verb, use a singular value. + +[1]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md diff --git a/site-src/ko/guides/backend-protocol.md b/site-src/ko/guides/backend-protocol.md new file mode 100644 index 0000000000..95870fd678 --- /dev/null +++ b/site-src/ko/guides/backend-protocol.md @@ -0,0 +1,36 @@ +# Backend Protocol + +??? success "Standard Channel since v1.2.0" + + This concept has been part of the Standard Channel since `v1.2.0`. + For more information on release channels, refer to our + [versioning guide](../concepts/versioning.md). + +Not all implementations of Gateway API support automatic protocol selection. In some cases protocols are disabled without an explicit opt-in. + +When a Route's backend references a Kubernetes Service, application developers can specify the protocol using `ServicePort` [`appProtocol`][appProtocol] field. + +For example the following `store` Kubernetes Service is indicating the port `8080` supports HTTP/2 Prior Knowledge. + + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: store +spec: + selector: + app: store + ports: + - protocol: TCP + appProtocol: kubernetes.io/h2c + port: 8080 + targetPort: 8080 +``` + +Currently, Gateway API has conformance testing for: + +- `kubernetes.io/h2c` - HTTP/2 Prior Knowledge +- `kubernetes.io/ws` - WebSocket over HTTP + +[appProtocol]: https://kubernetes.io/docs/concepts/services-networking/service/#application-protocol diff --git a/site-src/ko/guides/crd-management.md b/site-src/ko/guides/crd-management.md new file mode 100644 index 0000000000..7a9c05cc0f --- /dev/null +++ b/site-src/ko/guides/crd-management.md @@ -0,0 +1,110 @@ +# CRD Management + +Gateway API is built with CRDs. That comes with a number of significant +benefits, notably that each release of Gateway API supports the 5 more recent +minor versions of Kubernetes. That means you likely won't need to upgrade your +Kubernetes cluster to get the latest version of this API. + +Unfortunately, this extra flexibility also adds some room for confusion. This +guide aims to answer some of the most common questions related to Gateway API +CRD management. + +## Who Should Manage CRDs? + +Ultimately CRDs are a highly-privileged cluster-scoped resource. That means that +either a cluster admin or cluster provider should be responsible for managing +the CRDs in a cluster. + +Practically that means that any of the following are reasonable approaches: + +* Cluster admin installs CRDs +* Cluster provisioning tool or provider installs and manages CRDs + +Some implementations may also want to bundle CRDs to simplify installation. This +is acceptable as long as they never: + +1. Overwrite Gateway API CRDs that have unrecognized or newer versions. +1. Overwrite Gateway API CRDs that have a different release channel. +1. Remove Gateway API CRDs. + +[Issue #2678](https://github.com/kubernetes-sigs/gateway-api/issues/2678) +explores one possible approach implementations could use to accomplish this. + +## Upgrading to a new version + +Gateway API releases CRDs in two [release +channels](../concepts/versioning.md#release-channels). +Sticking with standard channel CRDs will ensure CRD upgrades are both simpler +and safer. + +### Overall Guidelines + +1. Avoid moving backwards. New versions of CRDs can add new fields and features. + Rolling back to a previous version of these CRDs could result in a loss of + that configuration. +1. Read the release notes before upgrading. In some cases, they may contain some + guidelines you need to follow before upgrading. +1. Understand the [Gateway API versioning policy](../concepts/versioning.md) so you + know what can change. +1. Although it is usually safe to upgrade across multiple Gateway API minor + versions at once, the safest and most widely tested path will involve + upgrading one minor version at a time. + +### Validating Webhook + +A validating webhook was included with earlier versions of Gateway API. Starting +in v1.0, that webhook has formally been deprecated in favor of the CEL +validation included directly within CRDs. In Gateway API v1.1, the webhook will +be fully removed. That means that the validating webhook is no longer a +consideration when upgrading to newer Gateway API versions. + +### API Version Removal + +!!! note + This is an advanced use case that is currently only applicable to users that + have been using Gateway API since v0.5.0 within the same cluster. + +It's possible that a Gateway API release will remove an alpha API version like +v1alpha2 in CRDs that have newer or more stable API versions. Within the +Standard Channel, the removal of an API version is spread into at least four +minor releases: + +1. A newer API version is configured as the storage version. +1. Version is deprecated (will be noted in release notes and via deprecation + warning when using deprecated API version). +1. Version is no longer served but is still included in the CRD for the sake + of automatic translation between API versions. +1. Version is no longer included in the CRD. + +If you were using a CRD that went through this process (including the storage +version migration), it's possible that some of your resources are stuck on the +older (deprecated) storage version. When a CRD storage version is updated, that +only takes effect when the individual resources using that CRD are saved again. + +For example, if you created a "foo" GatewayClass using Gateway API v0.5.0 CRDs, +the storage version of that GatewayClass would be v1alpha2. If that "foo" +GatewayClass had never been modified or updated by the time you would not be +able to upgrade to Gateway API v1.0.0 CRDs because one of our resources was +still using v1alpha2 as a storage version and that was no longer included in the +CRD (step 4 above). + +To be able to upgrade, you'd need to take some action that would update any +GatewayClasses that were using the old storage versions. For example, sending +an empty kubectl patch to each GatewayClass would have this effect. Fortunately +there's a tool that can automate this for us - +[kube-storage-version-migrator](https://github.com/kubernetes-sigs/kube-storage-version-migrator) +will automatically update resources to ensure they're using the latest storage +version. + +### Experimental Channel + +As the name implies, Experimental Channel does not provide the same stability +guarantees that Standard Channel does. When it comes to a minor release, any of +the following are possible for Experimental Channel CRDs: + +* Breaking changes for existing API fields or resources +* Removing API fields or resources without prior deprecation + +In practice this means that some upgrades to new Experimental versions may +require you to uninstall and reinstall the Experimental CRDs. If that is ever +the case, it will be clearly communicated in the release notes. diff --git a/site-src/ko/guides/grpc-routing.md b/site-src/ko/guides/grpc-routing.md new file mode 100644 index 0000000000..ba0fca2b94 --- /dev/null +++ b/site-src/ko/guides/grpc-routing.md @@ -0,0 +1,79 @@ +# gRPC routing + +The [GRPCRoute resource](../api-types/grpcroute.md) allows you to match on gRPC traffic and +direct it to Kubernetes backends. This guide shows how the GRPCRoute matches +traffic on host, header, and service, and method fields and forwards it to different +Kubernetes Services. + +The following diagram describes a required traffic flow across three different +Services: + +- Traffic to `foo.example.com` for the `com.Example.Login` method is forwarded to `foo-svc` +- Traffic to `bar.example.com` with an `env: canary` header is forwarded +to `bar-svc-canary` for all services and methods +- Traffic to `bar.example.com` without the header is forwarded to `bar-svc` for + all services and methods + + +![gRPC Routing](../images/grpc-routing.png) + +The dotted lines show the `Gateway` resources deployed to configure this routing +behavior. There are two `GRPCRoute` resources that create routing rules on the +same `prod` Gateway. This illustrates how more than one Route can bind to a +Gateway which allows Routes to merge on a `Gateway` as long as they don't +conflict. `GRPCRoute` follows the same Route merging semantics. For more +information on that, refer to the [documentation](../api-types/httproute.md#merging). + +In order to receive traffic from a [Gateway][gateway], a `GRPCRoute` resource +must be configured with `ParentRefs` which reference the parent gateway(s) that it +should be attached to. The following example shows how the combination +of `Gateway` and `GRPCRoute` would be configured to serve gRPC traffic: + +```yaml +{% include 'standard/grpc-routing/gateway.yaml' %} +``` + +A `GRPCRoute` can match against a [single set of hostnames][spec]. +These hostnames are matched before any other matching within the GRPCRoute takes +place. Since `foo.example.com` and `bar.example.com` are separate hosts with +different routing requirements, each is deployed as its own GRPCRoute - +`foo-route` and `bar-route`. + +The following `foo-route` will match any traffic for `foo.example.com` and apply +its routing rules to forward the traffic to the correct backend. Since there is +only one match specified, only requests for the `com.example.User.Login` method to +`foo.example.com` will be forwarded. RPCs of any other method` will not be matched +by this Route. + +```yaml +{% include 'standard/grpc-routing/foo-grpcroute.yaml' %} +``` + +Similarly, the `bar-route` GRPCRoute matches RPCs for `bar.example.com`. All +traffic for this hostname will be evaluated against the routing rules. The most +specific match will take precedence which means that any traffic with the `env: +canary` header will be forwarded to `bar-svc-canary` and if the header is +missing or does not have the value `canary` then it will be forwarded to `bar-svc`. + +```yaml +{% include 'standard/grpc-routing/bar-grpcroute.yaml' %} +``` + +[gRPC +Reflection](https://github.com/grpc/grpc/blob/v1.49.1/doc/server-reflection.md) +is required to use interactive clients such as +[`grpcurl`](https://github.com/fullstorydev/grpcurl) without having a local copy +of the target service's protocol buffers present on your local filesystem. To +enable this, first ensure that you have a gRPC reflection server listening on +your application pods, then add the reflection method to your `GRPCRoute`. This +is likely to be useful in development and staging environments, but this should +be enabled in production environments only after the security implications have +been considered. + +```yaml +{% include 'standard/grpc-routing/reflection-grpcroute.yaml' %} +``` + +[gateway]: ../reference/spec.md#gateway.networking.k8s.io/v1.Gateway +[spec]: ../reference/spec.md#gateway.networking.k8s.io%2fv1alpha2.GRPCRouteSpec +[svc]:https://kubernetes.io/docs/concepts/services-networking/service/ diff --git a/site-src/ko/guides/http-header-modifier.md b/site-src/ko/guides/http-header-modifier.md new file mode 100644 index 0000000000..1118124e00 --- /dev/null +++ b/site-src/ko/guides/http-header-modifier.md @@ -0,0 +1,65 @@ +# HTTP Header Modifiers + +[HTTPRoute resources](../api-types/httproute.md) can modify the headers of HTTP requests and the HTTP responses from clients. +There are two types of [filters](../api-types/httproute.md#filters-optional) available to meet these requirements: `RequestHeaderModifier` and `ResponseHeaderModifier`. + +This guide shows how to use these features. + +Note that these features are compatible. HTTP headers of the incoming requests and the headers of their responses can both be modified using a single [HTTPRoute resource](../api-types/httproute.md). + +## HTTP Request Header Modifier + +HTTP header modification is the process of adding, removing, or modifying HTTP headers in incoming requests. + +To configure HTTP header modification, define a Gateway object with one or more HTTP filters. Each filter specifies a specific modification to make to incoming requests, such as adding a custom header or modifying an existing header. + +To add a header to a HTTP request, use a filter of the type `RequestHeaderModifier`, with the `add` action and the name and value of the header: + +```yaml +{% include 'standard/http-request-header-add.yaml' %} +``` + +To edit an existing header, use the `set` action and specify the value of the header to be modified and the new header value to be set. + +```yaml + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: my-header-name + value: my-new-header-value +``` + +Headers can also be removed, by using the `remove` keyword and a list of header names. + +```yaml + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + remove: ["x-request-id"] +``` + +Using the example above would remove the `x-request-id` header from the HTTP request. + +### HTTP Response Header Modifier + +Just like editing request headers can be useful, the same goes for response headers. For example, it allows teams to add/remove cookies for only a certain backend, which can help in identifying certain users that were redirected to that backend previously. + +Another potential use case could be when you have a frontend that needs to know whether it’s talking to a stable or a beta version of the backend server, in order to render different UI or adapt its response parsing accordingly. + +Modifying the HTTP header response leverages a very similar syntax to the one used to modify the original request, albeit with a different filter (`ResponseHeaderModifier`). + +Headers can be added, edited and removed. Multiple headers can be added, as shown in this example below: + +```yaml + filters: + - type: ResponseHeaderModifier + responseHeaderModifier: + add: + - name: X-Header-Add-1 + value: header-add-1 + - name: X-Header-Add-2 + value: header-add-2 + - name: X-Header-Add-3 + value: header-add-3 +``` diff --git a/site-src/ko/guides/http-redirect-rewrite.md b/site-src/ko/guides/http-redirect-rewrite.md new file mode 100644 index 0000000000..37a887d057 --- /dev/null +++ b/site-src/ko/guides/http-redirect-rewrite.md @@ -0,0 +1,114 @@ +# HTTP path redirects and rewrites + +[HTTPRoute resources](../api-types/httproute.md) can issue redirects to +clients or rewrite paths sent upstream using +[filters](../api-types/httproute.md#filters-optional). This guide shows how +to use these features. + +Note that redirect and rewrite filters are mutually incompatible. Rules cannot +use both filter types at once. + +## Redirects + +Redirects return HTTP 3XX responses to a client, instructing it to retrieve a +different resource. [`RequestRedirect` rule +filters](../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRequestRedirectFilter) +instruct Gateways to emit a redirect response to requests matching a filtered +HTTPRoute rule. + +Redirect filters can substitute various URL components independently. For +example, to issue a permanent redirect (301) from HTTP to HTTPS, configure +`requestRedirect.statusCode=301` and `requestRedirect.scheme="https"`: + +```yaml +{% include 'standard/http-redirect-rewrite/httproute-redirect-http.yaml' %} +``` + +Redirects change configured URL components to match the redirect configuration +while preserving other components from the original request URL. In this +example, the request `GET http://redirect.example/cinnamon` will result in a +301 response with a `location: https://redirect.example/cinnamon` header. The +hostname (`redirect.example`), path (`/cinnamon`), and port (implicit) remain +unchanged. + +### HTTP-to-HTTPS redirects + +To redirect HTTP traffic to HTTPS, you need to have a Gateway with both HTTP +and HTTPS listeners. + +```yaml +{% include 'standard/http-redirect-rewrite/gateway-redirect-http-https.yaml' %} +``` +There are multiple ways to secure a Gateway. In this example, it is secured +using a Kubernetes Secret(`redirect-example` in the `certificateRefs` section). + +You need a HTTPRoute that attaches to the HTTP listener and does the redirect +to HTTPS. Here we set `sectionName` to be `http` so it only selects the +listener named `http`. + +```yaml +{% include 'standard/http-redirect-rewrite/httproute-redirect-http.yaml' %} +``` + +You also need a HTTPRoute that attaches to the HTTPS listener that forwards +HTTPS traffic to application backends. + +```yaml +{% include 'standard/http-redirect-rewrite/httproute-redirect-https.yaml' %} +``` + +### Path redirects + +Path redirects use an HTTP Path Modifier to replace either entire paths or path +prefixes. For example, the HTTPRoute below will issue a 302 redirect to all +`redirect.example` requests whose path begins with `/cayenne` to `/paprika`: + +```yaml +{% include 'standard/http-redirect-rewrite/httproute-redirect-full.yaml' %} +``` + +Both requests to +`https://redirect.example/cayenne/pinch` and +`https://redirect.example/cayenne/teaspoon` will receive a redirect with a +`location: https://redirect.example/paprika`. + +The other path redirect type, `ReplacePrefixMatch`, replaces only the path +portion matching `matches.path.value`. Changing the filter in the above to: + +```yaml +{% include 'standard/http-redirect-rewrite/httproute-redirect-prefix.yaml' %} +``` + +will result in redirects with `location: +https://redirect.example/paprika/pinch` and `location: +https://redirect.example/paprika/teaspoon` response headers. + +## Rewrites + +Rewrites modify components of a client request before proxying it upstream. A +[`URLRewrite` +filter](../reference/spec.md#gateway.networking.k8s.io/v1.HTTPURLRewriteFilter) +can change the upstream request hostname and/or path. For example, the +following HTTPRoute will accept a request for +`https://rewrite.example/cardamom` and send it upstream to `example-svc` with +`host: elsewhere.example` in request headers instead of `host: +rewrite.example`. + +```yaml +{% include 'standard/http-redirect-rewrite/httproute-rewrite.yaml' %} +``` + +Path rewrites also make use of HTTP Path Modifiers. The HTTPRoute below +will take request for `https://rewrite.example/cardamom/smidgen` and proxy a +request to `https://elsewhere.example/fennel` upstream to `example-svc`. + +```yaml +{% include 'standard/http-redirect-rewrite/httproute-rewrite-full-path.yaml' %} +``` + +Instead using `type: ReplacePrefixMatch` and `replacePrefixMatch: /fennel` will +request `https://elsewhere.example/fennel/smidgen` upstream. + +```yaml +{% include 'standard/http-redirect-rewrite/httproute-rewrite-prefix-path.yaml' %} +``` diff --git a/site-src/ko/guides/http-request-mirroring.md b/site-src/ko/guides/http-request-mirroring.md new file mode 100644 index 0000000000..61b7e27bb6 --- /dev/null +++ b/site-src/ko/guides/http-request-mirroring.md @@ -0,0 +1,27 @@ +# HTTP request mirroring + +??? example "Extended Support Feature" + + As of v1.0.0, the Request Mirroring feature is an Extended feature, and + requires implementations to support the `HTTPRouteRequestMirror` feature. + +The [HTTPRoute resource](../api-types/httproute.md) allows you to mirror HTTP +requests to another backend using +[filters](../api-types/httproute.md#filters-optional). This guide shows how to use +this feature. + +Mirrored requests will must only be sent to one single destination endpoint +within this backendRef, and responses from this backend MUST be ignored by +the Gateway. + +Request mirroring is particularly useful in blue-green deployment. It can be +used to assess the impact on application performance without impacting +responses to clients in any way. + +```yaml +{% include 'standard/http-request-mirroring/httproute-mirroring.yaml' %} +``` + +In this example, all requests are forwarded to service `foo-v1` on port `8080`, +and they are also forwarded to service `foo-v2` on port `8080`, but responses +are only generated from service `foo-v1`. diff --git a/site-src/ko/guides/http-routing.md b/site-src/ko/guides/http-routing.md new file mode 100644 index 0000000000..72112ec65d --- /dev/null +++ b/site-src/ko/guides/http-routing.md @@ -0,0 +1,62 @@ +# HTTP routing + +The [HTTPRoute resource](../api-types/httproute.md) allows you to match on HTTP traffic and +direct it to Kubernetes backends. This guide shows how the HTTPRoute matches +traffic on host, header, and path fields and forwards it to different +Kubernetes Services. + +The following diagram describes a required traffic flow across three different +Services: + +- Traffic to `foo.example.com/login` is forwarded to `foo-svc` +- Traffic to `bar.example.com/*` with a `env: canary` header is forwarded +to `bar-svc-canary` +- Traffic to `bar.example.com/*` without the header is forwarded to `bar-svc` + +![HTTP Routing](../images/http-routing.png) + +The dotted lines show the Gateway resources deployed to configure this routing +behavior. There are two HTTPRoute resources that create routing rules on the +same `prod-web` Gateway. This illustrates how more than one Route can bind to a +Gateway which allows Routes to merge on a Gateway as long as they don't +conflict. For more information on Route merging, refer to the [HTTPRoute +documentation](../api-types/httproute.md#merging). + +In order to receive traffic from a [Gateway][gateway] an `HTTPRoute` resource +must be configured with `ParentRefs` which reference the parent gateway(s) that it +should be attached to. The following example shows how the combination +of `Gateway` and `HTTPRoute` would be configured to serve HTTP traffic: + +```yaml +{% include 'standard/http-routing/gateway.yaml' %} +``` + +An HTTPRoute can match against a [single set of hostnames][spec]. +These hostnames are matched before any other matching within the HTTPRoute takes +place. Since `foo.example.com` and `bar.example.com` are separate hosts with +different routing requirements, each is deployed as its own HTTPRoute - +`foo-route` and `bar-route`. + +The following `foo-route` will match any traffic for `foo.example.com` and apply +its routing rules to forward the traffic to the correct backend. Since there is +only one match specified, only `foo.example.com/login/*` traffic will be +forwarded. Traffic to any other paths that do not begin with `/login` will not +be matched by this Route. + +```yaml +{% include 'standard/http-routing/foo-httproute.yaml' %} +``` + +Similarly, the `bar-route` HTTPRoute matches traffic for `bar.example.com`. All +traffic for this hostname will be evaluated against the routing rules. The most +specific match will take precedence which means that any traffic with the `env: +canary` header will be forwarded to `bar-svc-canary` and if the header is +missing or not `canary` then it'll be forwarded to `bar-svc`. + +```yaml +{% include 'standard/http-routing/bar-httproute.yaml' %} +``` + +[gateway]: ../reference/spec.md#gateway.networking.k8s.io/v1.Gateway +[spec]: ../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteSpec +[svc]:https://kubernetes.io/docs/concepts/services-networking/service/ diff --git a/site-src/ko/guides/implementers.md b/site-src/ko/guides/implementers.md new file mode 100644 index 0000000000..255be26a53 --- /dev/null +++ b/site-src/ko/guides/implementers.md @@ -0,0 +1,357 @@ +# Implementer's Guide + +Everything you wanted to know about building a Gateway API implementation +but were too afraid to ask. + +This document is a place to collect tips and tricks for _writing a Gateway API +implementation_ that have no straightforward place within the godoc fields of the +underlying types. + +It's also intended to be a place to write down some guidelines to +help implementers of this API to skip making common mistakes. + +It may not be very relevant if you are intending to _use_ this API as an end +user as opposed to _building_ something that uses it. + +This is a living document, if you see something missing, PRs welcomed! + +## Important things to remember about Gateway API + +Hopefully most of these are not surprising, but they sometimes have non-obvious +implications that we'll try and lay out here. + +### Gateway API is a `kubernetes.io` API + +Gateway API uses the `gateway.networking.k8s.io` API group. This means that, +like APIs delivered in the core Kubernetes binaries, each time a release happens, +the APIs have been reviewed by upstream Kubernetes reviewers, just like the APIs +delivered in the core binaries. + +### Gateway API is delivered using CRDs + +Gateway API is supplied as a set of CRDs, version controlled using our [versioning +policy][versioning]. + +The most important part of that versioning policy is that what _appears to be_ +the same object (that is, it has the same `group`,`version`, and `kind`) may have +a slightly different schema. We make changes in ways that are _compatible_, so +things should generally "just work", but there are some actions implementations +need to take to make "just work"ing more reliable; these are detailed below. + +The CRD-based delivery also means that if an implementation tries to use (that is +get, list, watch, etc) Gateway API objects when the CRDs have _not_ been installed, +then it's likely that your Kubernetes client code will return serious errors. +Tips to deal with this are also detailed below. + +The CRD definitions for Gateway API objects all contain two specific +annotations: + +- `gateway.networking.k8s.io/bundle-version: ` +- `gateway.networking.k8s.io/channel: ` + +The concepts of "bundle version" and "channel" (short for "release channel") are +explained in our [versioning][versioning] documentation. + +Implementations may use these to determine what schema versions are installed in +the cluster, if any. + +[versioning]: ../concepts/versioning.md + +### Changes to the Standard Channel CRDs are backwards compatible + +Part of the contract for Standard Channel CRDs is that changes _within an API +version_ must be _compatible_. Note that CRDs that are part of Experimental +Channel do not provide any backwards compatibility guarantees. + +Although the [Gateway API versioning policy](../concepts/versioning.md) largely +aligns with upstream Kubernetes APIs, it does allow for "corrections to +validation". For example, if the API spec stated that a value was invalid but +the corresponding validation did not cover that, it's possible that a future +release may add validation to prevent that invalid input. + +This contract also means that an implementation will not fail with a higher +version of the API than the version it was written with, because the newer +schema being stored by Kubernetes will definitely be able to be serialized into +the older version used in code by the implementation. + +Similarly, if an implementation was written with a _higher_ version, the newer +values that it understands will simply _never be used_, as they are not present +in the older version. + +## Implementation Rules and Guidelines + +### CRD Management + +For information on how to manage Gateway API CRDs, including when it is +acceptable to bundle CRD installation with your implementation, refer to our +[CRD Management Guide](crd-management.md). + +### Conformance and Version Compatibility + +A conformant Gateway API implementation is one that passes the conformance tests +that are included in each Gateway API bundle version release. + +An implementation MUST pass the conformance suite with _no_ skipped tests to be +conformant. Tests may be skipped during development, but a version you want to +be conformant MUST have no skipped tests. + +Extended features may, as per the contract for Extended status, be disabled. + +Gateway API conformance is version-specific. An implementation that passes +conformance for version N may not pass conformance for version N+1 without changes. + +Implementations SHOULD submit a report from the conformance testing suite back +to the Gateway API GitHub repo containing details of their testing. + +The conformance suite output includes the Gateway API version supported. + +#### Version Compatibility + +Once v1.0 is released, for implementations supporting Gateway and GatewayClass, +they MUST set a new Condition, `SupportedVersion`, with `status: true` meaning +that the installed CRD version is supported, and `status: false` meaning that it +is not. + +### Standard Status Fields and Conditions + +Gateway API has many resources, but when designing this, we've worked to keep +the status experience as consistent as possible across objects, using the +Condition type and the `status.conditions` field. + +Most resources have a `status.conditions` field, but some also have a namespaced +field that _contains_ a `conditions` field. + +For the latter, Gateway's `status.listeners` and the Route `status.parents` +fields are examples where each item in the slice identifies the Conditions +associated with some subset of configuration. + +For the Gateway case, it's to allow Conditions per _Listener_, and in the Route +case, it's to allow Conditions per _implementation_ (since Route objects can +be used in multiple Gateways, and those Gateways can be reconciled by different +implementations). + +In all of these cases, there are some relatively-common Condition types that have +similar meanings: + +- `Accepted` - the resource or part thereof contains acceptable config that will +produce some configuration in the underlying data plane that the implementation +controls. This does not mean that the _whole_ configuration is valid, just that +_enough_ is valid to produce some effect. +- `Programmed` - this represents a later phase of operation, after `Accepted`, +when the resource or part thereof has been Accepted and programmed into the +underlying dataplane. Users should expect the configuration to be ready for +traffic to flow _at some point in the near future_. This Condition does _not_ +say that the dataplane is ready _when it's set_, just that everything is valid +and it _will become ready soon_. "Soon" may have different meanings depending +on the implementation. +- `ResolvedRefs` - this Condition indicates that all references in the resource +or part thereof were valid and pointed to an object that both exists and allows +that reference. If this Condition is set to `status: false`, then _at least one_ +reference in the resource or part thereof is invalid for some reason, and the +`message` field should indicate which one are invalid. + +Implementers should check the godoc for each type to see the exact details of +these Conditions on each resource or part thereof. + +Additionally, the upstream `Conditions` struct contains an optional +`observedGeneration` field - implementations MUST use this field and set it to +the `metadata.generation` field of the object at the time the status is generated. +This allows users of the API to determine if the status is relevant to the current +version of the object. + +## TLS + +TLS is a large topic in Gateway API, with the set of capabilities continuing to +expand. There is a [TLS guide](tls.md) that covers this topic in more depth +from a user-facing perspective, but this section attempts to fill in some gaps +from an implementer's perspective. + +### Listener Isolation +Within Gateways, TLS config is currently tied exclusively to Listeners. To make +that approach manageable, we're encouraging all implementations to work towards +the goal of providing full "Listener Isolation" as defined below: + +Requests SHOULD match at most one Listener. For example, if Listeners are +defined for "foo.example.com" and "*.example.com", a request to +"foo.example.com" SHOULD only be routed using routes attached to the +"foo.example.com" Listener (and not the "*.example.com" Listener). + +Implementations that do not support Listener Isolation MUST clearly document +this. In the future, we plan to add HTTPS Listener Isolation conformance tests +to ensure this behavior is consistent across implementations that claim support +for the feature. See +[#2803](https://github.com/kubernetes-sigs/gateway-api/issues/2803) for the +latest updates on these tests. + +### Indirect Configuration +There are a variety of instances where TLS Certificates may not be managed +directly by the owner of a Gateway. Although this is not meant to be an +exhaustive list, it documents some of the approaches we expect to see used to +manage TLS Certificates with Gateway API: + +#### 1. Certificates from other places +Some providers offer the ability to configure and host TLS Certificates outside +of Kubernetes altogether. Implementations that can connect to those external +providers may expose that capability via a TLS option on the Gateway Listener, +for example: + +``` + listeners: + - name: https + protocol: HTTPS + port: 443 + tls: + mode: Terminate + options: + vendor.example.com/certificate-name: store-example-com +``` + +In this example, the `store-example-com` name would refer to the name of a +certificate stored by the external `vendor.example.com` TLS Certificate +provider. + +#### 2. Automatically generated TLS certs that are populated later +Many users would prefer that TLS certs will be automatically generated on their +behalf. One potential implementation of that would involve a controller that +watches Gateways and HTTPRoutes, generates TLS certs, and attaches them to the +Gateway. Depending on the implementation details, Gateway owners may need to +configure something at the Gateway or Listener level to explicitly opt-in to +this feature. For example, let's say someone created `acme-cert-generator` to +generate certs following this pattern. That generator may choose to only +generate and populate certs on Gateway Listeners with `acme.io/cert-generator` +set in `tls.options` or a similar annotation set for the entire Gateway. + +Note that this is actually fairly similar to [how Cert Manager works +today](https://cert-manager.io/docs/usage/gateway/), but that requires Gateway +owners to reference a Kubernetes Secret that it will then populate. This +specific approach was required because TLS CertificateRefs were required to be +specified until Gateway API v1.1. + +With the relaxing of Gateway API validation in v1.1, TLS Certificates can be +left unspecified on creation, allowing for less configuration when working with +generated TLS certificates. + +#### 3. Certs that are specified by other personas +In some organizations, Application Developers are responsible for managing TLS +Certificates (see [Roles and Personas](../concepts/roles-and-personas.md) for more on +this and other roles). + +To enable this use case, a new controller and CRD would be created. This +CRD would link hostnames to user-provided certs, and then the controller would +populate the certs specified by that CRD on Gateway listeners that matched those +hostnames. This would also likely benefit from a Listener or Gateway-level +opt-in for the behavior. + +### Overall Guidelines for TLS Extensions +When building TLS extensions on top of Gateway API, it's important to follow the +following guidelines: + +1. Use domain-prefixed names that are unique to your implementation for any TLS + Options or Annotations. (For example, use `example.com/certificate-name` + instead of just `certificate-name`). +2. Do not encode sensitive information like certificates in the option or + annotation value. Instead favor references via concise names that are easy + to understand. Although these values can technically be as long as 253 + characters, we strongly recommend keeping the values below 50 characters to + maintain overall readability and UX. +3. To enable these extensions, Gateway API v1.1+ will no longer require TLS + Config to be specified on Gateway Listeners. When a Gateway Listener does not + have sufficient TLS configuration specified, implementations MUST set the + `Programmed` condition to `False` for that Listener with the + `InvalidTLSConfig` reason. +4. Regardless of any extensions you may choose to support, it is important to + support the core TLS configuration that is intended to be portable across all + implementations. Extensions have their place in this API, but all + implementations MUST still support the core capabilities of the API. + +## Resource Details + +For each currently available conformance profile, there are a set of resources +that implementations are expected to reconcile. + +The following section goes through each Gateway API object and indicates expected +behaviors. + +### GatewayClass + +GatewayClass has one main `spec` field - `controllerName`. Each implementation +is expected to claim a domain-prefixed string value (like +`example.com/example-ingress`) as its `controllerName`. + +Implementations MUST watch _all_ GatewayClasses, and reconcile GatewayClasses +that have a matching `controllerName`. The implementation must choose at least +one compatible GatewayClass out of the set of GatewayClasses that have a matching +`controllerName`, and indicate that it accepts processing of that GatewayClass +by setting an `Accepted` Condition to `status: true` in each. Any GatewayClasses +that have a matching `controllerName` but are _not_ Accepted must have the +`Accepted` Condition set to `status: false`. + +Implementations MAY choose only one GatewayClass out of the pool of otherwise +acceptable GatewayClasses if they can only reconcile one, or, if they are capable +of reconciling multiple GatewayClasses, they may also choose as many as they like. + +If something in the GatewayClass renders it incompatible (at the time of writing, +the only possible reason for this is that there is a pointer to a `paramsRef` +object that is not supported by the implementation), then the implementation +SHOULD mark the incompatible GatewayClass as not `Accepted`. + +### Gateway + +Gateway objects MUST refer in the `spec.gatewayClassName` field to a GatewayClass +that exists and is `Accepted` by an implementation for that implementation to +reconcile them. + +Gateway objects that fall out of scope (for example, because the GatewayClass +they reference was deleted) for reconciliation MAY have their status removed by +the implementation as part of the delete process, but this is not required. + +### Routes + +All Route objects share some properties: + +- They MUST be attached to an in-scope parent for the implementation to consider + them reconcilable. +- The implementation MUST update the status for each in-scope Route with the + relevant Conditions, using the namespaced `parents` field. See the specific + Route types for details, but this usually includes `Accepted`, `Programmed` + and `ResolvedRefs` Conditions. +- Routes that fall out of scope SHOULD NOT have status updated, since it's + possible that these updates may overwrite any new owners. The + `observedGeneration` field will indicate that any remaining status is out of + date. + +#### HTTPRoute + +HTTPRoutes route HTTP traffic that is _unencrypted_ and available for inspection. +This includes HTTPS traffic that's terminated at the Gateway (since that is then +decrypted), and allows the HTTPRoute to use HTTP properties, like path, method, +or headers in its routing directives. + +#### TLSRoute + +TLSRoutes route encrypted TLS traffic using the SNI header, _without decrypting +the traffic stream_, to the relevant backends. + +#### TCPRoute + +TCPRoutes route a TCP stream that arrives at a Listener to one of the given +backends. + +#### UDPRoute + +UDPRoutes route UDP packets that arrive at a Listener to one of the given +backends. + +### ReferenceGrant + +ReferenceGrant is a special resource that is used by resource owners in one +namespace to _selectively_ allow references from Gateway API objects in other +namespaces. + +A ReferenceGrant is created in the same namespace as the thing it's granting +reference access to, and allows access from other namespaces, from other Kinds, +or both. + +Implementations that support cross-namespace references MUST watch ReferenceGrant +and reconcile any ReferenceGrant that points to an object that's referred to by +an in-scope Gateway API object. diff --git a/site-src/ko/guides/index.md b/site-src/ko/guides/index.md new file mode 100644 index 0000000000..21fbe942b1 --- /dev/null +++ b/site-src/ko/guides/index.md @@ -0,0 +1,193 @@ +# Getting started with Gateway API + +**1.** **[Install a Gateway controller](#installing-a-gateway-controller)** + _OR_ **[install the Gateway API CRDs manually](#installing-gateway-api)** + +_THEN_ + +**2.** **Try out one of the available guides:** + +- [Simple Gateway](simple-gateway.md) (a good one to start out with) +- [HTTP routing](http-routing.md) +- [HTTP redirects and rewrites](http-redirect-rewrite.md) +- [HTTP traffic splitting](traffic-splitting.md) +- [Routing across Namespaces](multiple-ns.md) +- [Configuring TLS](tls.md) +- [TCP routing](tcp.md) +- [gRPC routing](grpc-routing.md) +- [Migrating from Ingress](migrating-from-ingress.md) + +## Installing a Gateway controller + +There are [multiple projects](../implementations.md) that support Gateway API. By +installing a Gateway controller in your Kubernetes cluster, you can try out the +guides above. This will demonstrate that the desired routing configuration is +actually being implemented by your Gateway resources (and the network +infrastructure that your Gateway resources represent). Note that many of the +Gateway controller setups will install and remove the Gateway API bundle for +you. + +## Installing Gateway API + +!!! danger "Upgrades from earlier Experimental Channel releases" + + If you've previously installed an earlier version of experimental channel, + refer to the [v1.1 upgrade notes](#v11-upgrade-notes). + +A Gateway API bundle represents the set of CRDs associated with a version of +Gateway API. Each release includes two channels with different levels of +stability: + +### Install Standard Channel + +The standard release channel includes all resources that have graduated to GA or +beta, including GatewayClass, Gateway, HTTPRoute, and ReferenceGrant. To install +this channel, run the following kubectl command: + +```bash +kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml +``` + +### Install Experimental Channel + +The experimental release channel includes everything in the standard release +channel plus some experimental resources and fields. This includes +TCPRoute, TLSRoute, and UDPRoute. + +Note that future releases of the API could include breaking changes to +experimental resources and fields. For example, any experimental resource or +field could be removed in a future release. For more information on the +experimental channel, refer to our [versioning +documentation](../concepts/versioning.md). + +To install the experimental channel, run the following kubectl command: + +```bash +kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/experimental-install.yaml +``` + +### v1.2 Upgrade Notes +Before upgrading to Gateway API v1.2, you'll want to confirm that any +implementations of Gateway API have been upgraded to support the `v1` API +version of these resources instead of the `v1alpha2` API version. Note that +even if you've been using `v1` in your YAML manifests, a controller may still be +using `v1alpha2` which would cause it to fail during this upgrade. + +Once you've confirmed that the implementations you're relying on have upgraded +to v1, it's time to install the v1.2 CRDs. In most cases, this will work without +any additional effort. + +If you ran into issues installing these CRDs, it likely means that you have +`v1alpha2` in the `storedVersions` of one or both of these CRDs. This field is +used to indicate which API versions have ever been used to persist one of these +resources. Unfortunately, this field is not automatically pruned. To check these +values, you can run the following commands: + +``` +kubectl get crd grpcroutes.gateway.networking.k8s.io -ojsonpath="{.status.storedVersions}" +kubectl get crd referencegrants.gateway.networking.k8s.io -ojsonpath="{.status.storedVersions}" +``` + +If either of these return a list that includes "v1alpha2", it means that we need +to manually remove that version from `storedVersions`. + +Before doing that, it would be good to ensure that all your ReferenceGrants and +GRPCRoutes have been updated to the latest storage version: + +``` +crds=("GRPCRoutes" "ReferenceGrants") + +for crd in "${crds[@]}"; do + output=$(kubectl get "${crd}" -A -o json) + + echo "$output" | jq -c '.items[]' | while IFS= read -r resource; do + namespace=$(echo "$resource" | jq -r '.metadata.namespace') + name=$(echo "$resource" | jq -r '.metadata.name') + kubectl patch "${crd}" "${name}" -n "${namespace}" --type='json' -p='[{"op": "replace", "path": "/metadata/annotations/migration-time", "value": "'"$(date +%Y-%m-%dT%H:%M:%S)"'" }]' + done +done +``` + +Now that all your ReferenceGrant and GRPCRoute resources have been updated to +use the latest storage version, you can patch the ReferenceGrant and GRPCRoute +CRDs: + +``` +kubectl patch customresourcedefinitions referencegrants.gateway.networking.k8s.io --subresource='status' --type='merge' -p '{"status":{"storedVersions":["v1beta1"]}}' +kubectl patch customresourcedefinitions grpcroutes.gateway.networking.k8s.io --subresource='status' --type='merge' -p '{"status":{"storedVersions":["v1"]}}' +``` + +With these steps complete, upgrading to the latest GRPCRoute and ReferenceGrant +should work well now. + +### v1.1 Upgrade Notes +If you are already using previous versions of GRPCRoute or BackendTLSPolicy +experimental channel CRDs from previous Gateway API releases, you'll need to be +careful with this upgrade. If you haven't installed Gateway API before, or have +exclusively used the standard channel of the API, you can skip the rest of this +section. + +#### GRPCRoute +**Summary:** If you're already using v1alpha2 GRPCRoute, stick with the +experimental channel of GRPCRoute in v1.1 until the implementation(s) you're +relying on have been updated to support GRPCRoute v1. + +**Explanation:** With the graduation of GRPCRoute to GA, it is now included in +standard channel. Unfortunately, that can be problematic for anyone that was +already using the experimental channel version of GRPCRoute. As a rule, CRDs in +standard channel do not expose alpha API version to avoid any version +deprecations in that channel. That means that the standard channel version of +GRPCRoute excludes v1alpha2. All implementations of GRPCRoute built before the +v1.1 release of Gateway API would have exclusively relied on v1alpha2 and will +need to be updated to support GRPCRoute v1. Until implementations have been +updated to support v1, you can safely upgrade to the experimental channel +version of GRPCRoute included in v1.1 that exposes both v1 and v1alpha2. + +**Upgrade Sequence:** If you're already using v1alpha2 GRPCRoute, we'd recommend +the following upgrade sequence: + +1. Install *experimental* v1.1 GRPCRoute CRD +2. Update all your manifests to use `v1` instead of `v1alpha2` +3. Upgrade to an implementation that supports GRPCRoute `v1` API Version +4. Install *standard* channel v1.1 GRPCRoute CRD + +#### BackendTLSPolicy +**Summary:** If you've previously installed BackendTLSPolicy, wait until the +implementation(s) you're relying on have been updated to support `v1alpha3` of +the API. When upgrading to an implementation that supports `v1alpha3`, you'll +also need to uninstall the old BackendTLSPolicy CRD before installing the new +one. + +**Explanation:** BackendTLSPolicy had several significant fields renamed in +v1.1, resulting in a version bump to v1alpha3. As this is experimental channel, +we are not providing an in-place upgrade path for this change, instead you'll +need to coordinate the CRD upgrade with the implementation(s) of +BackendTLSPolicy that you're relying on. + +**Upgrade Sequence:** If you're already using v1alpha2 BackendTLSPolicy, we'd +recommend the following upgrade sequence: + +1. Wait for your implementation of choice to release support for v1alpha3 +2. Delete the older pre-v1.1 BackendTLSPolicy CRD (this will also delete all + instances of BackendTLSPolicy in your cluster) +3. Install the new v1.1 BackendTLSPolicy CRD +4. Deploy the version of your implementation that supports BackendTLSPolicy v1alpha3 + +Note that some implementations may prefer switching the order of steps 3 and 4, +it's worth checking with any relevant release notes for your implementation of +choice. + + +### Cleanup + +After you're done, you can clean up after yourself by uninstalling the Gateway +API CRDs by replacing "apply" with "delete" in the commands above. If these +resources are in-use or if they were installed by a Gateway controller, then do +not uninstall them. This will uninstall the Gateway API resources for the entire +cluster. Do not do this if they might be in-use by someone else as this will +break anything using these resources. + +### More on CRD Management +This guide only provides a high level overview of how to get started with +Gateway API. For more on the topic of managing Gateway API CRDs, refer to our +[CRD Management Guide](crd-management.md). diff --git a/site-src/ko/guides/infrastructure.md b/site-src/ko/guides/infrastructure.md new file mode 100644 index 0000000000..42e7f0b33a --- /dev/null +++ b/site-src/ko/guides/infrastructure.md @@ -0,0 +1,45 @@ +# Gateway infrastructure labels and annotations + +??? success "Standard Channel since v1.2.0" + + The `infrastructure` field is GA and has been part of the Standard Channel since + `v1.2.0`. For more information on release channels, refer to our [versioning + guide](../concepts/versioning.md). + +Gateway API implementations are responsible for creating the backing +infrastructure needed to make each Gateway work. For example, implementations +running in a Kubernetes cluster often create [Services][service] and +[Deployments][deployment], while cloud-based implementations may create cloud +load balancer resources. In many cases, it can be helpful to be able to +propagate labels or annotations to these generated resources. + + +The [`infrastructure` field][infrastructure] on a Gateway allows you to specify +labels and annotations for the infrastructure created by the Gateway API controller. +For example, if your Gateway infrastructure is running in-cluster, you can specify +both Linkerd and Istio injection using the following Gateway configuration, making +it simpler for the infrastructure to be incorporated into whichever service mesh +you've installed. + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: meshed-gateway + namespace: incoming +spec: + gatewayClassName: meshed-gateway-class + listeners: + - name: http-listener + protocol: HTTP + port: 80 + infrastructure: + labels: + istio-injection: enabled + annotations: + linkerd.io/inject: enabled +``` + +[infrastructure]: ../reference/spec.md#gateway.networking.k8s.io/v1.GatewayInfrastructure +[service]: https://kubernetes.io/docs/concepts/services-networking/service/ +[deployment]: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/ diff --git a/site-src/ko/guides/migrating-from-ingress.md b/site-src/ko/guides/migrating-from-ingress.md new file mode 100644 index 0000000000..77fef68de0 --- /dev/null +++ b/site-src/ko/guides/migrating-from-ingress.md @@ -0,0 +1,434 @@ +# Migrating from Ingress + +Gateway API project is the successor to the [Ingress API][ing]. However, it +does not include the Ingress resource (the closest parallel is the HTTPRoute). +As a result, a one-time conversion from your existing Ingress resources to the +relevant Gateway API resources is necessary. + +[ing]:https://kubernetes.io/docs/concepts/services-networking/ingress/ + +This guide will help you with the conversion. It will: + +* Explain why you may want to switch to Gateway API. +* Describe the key differences between the Ingress API and Gateway API. +* Map Ingress features to Gateway API features. +* Show an example of an Ingress resource converted to Gateway API resources. +* Mention [ingress2gateway](https://github.com/kubernetes-sigs/ingress2gateway) + for automatic conversion. + +At the same time, it will not prepare you for a live migration or explain how to +convert some implementation-specific features of your Ingress controller. +Additionally, since the Ingress API only covers HTTP/HTTPS traffic, this guide +does not cover Gateway API support for other protocols. + +## Reasons to Switch to Gateway API + +The [Ingress API](https://kubernetes.io/docs/concepts/services-networking/ingress/) +is the standard Kubernetes way to configure external HTTP/HTTPS load balancing +for Services. It is widely adopted by Kubernetes users and well-supported by +vendors with many implementations ([Ingress controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/)) +available. Additionally, several cloud-native projects integrate with the +Ingress API, such as [cert-manager](https://cert-manager.io/) +and [ExternalDNS](https://github.com/kubernetes-sigs/external-dns). + +However, the Ingress API has several limitations: + +- *Limited features*. The Ingress API only supports TLS termination and + simple content-based request routing of HTTP traffic. +- *Reliance on annotations for extensibility*. The annotations approach to + extensibility leads to limited portability as every implementation has its own + supported extensions that may not translate to any other implementation. +- *Insufficient permission model*. The Ingress API is not well-suited for + multi-team clusters with shared load-balancing infrastructure. + +Gateway API addresses those limitations, as the next section will show. + +> Read more about the [design goals](../index.md#gateway-api-concepts) +> of Gateway API. + +## Key Differences Between Ingress API and Gateway API + +There are three major differences between the Ingress API and Gateway API: + +* Personas +* Available features +* Approach to extensibility (implementation-specific features) + +### Personas + +At first, the Ingress API had only a single resource kind Ingress. As a result, +it had only one persona -- the user -- the owner of Ingress resources. The +Ingress features give the user a lot of control over how applications are +exposed to their external clients, including TLS termination configuration and +provisioning of the load balancing infrastructure (supported by some Ingress +controllers). Such a level of control is called the self-service model. + +At the same time, the Ingress API also included two implicit personas to +describe somebody responsible for provisioning and managing an Ingress +controller: the infrastructure provider for provider-managed Ingress controllers +and the cluster operator (or admin) for self-hosted Ingress controllers. With +the late addition of +the [IngressClass](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) +resource, the infrastructure provider and cluster operator became the owners of +that resource, and thus, explicit personas of the Ingress API. + +Gateway API +includes [four explicit personas](../concepts/security-model.md#roles-and-personas): +the application developer, the application admin, the cluster operator, and the +infrastructure providers. This allows you to break away from the self-service +model by splitting the responsibilities of the user persona across those +personas (all except the infrastructure provider): + +* The cluster operator/application admin defines entry points for the external + client traffic including TLS termination configuration. +* The application developer defines routing rules for their applications that + attach to those entry points. + +Such a split adheres to a common organizational structure where multiple teams +share the same load-balancing infrastructure. At the same time, it is not +mandatory to give up the self-service model -- it is still possible to configure +a single RBAC Role that will fulfill the application developer, application +admin, and cluster operator responsibilities. + +The table below summarizes the mapping between the Ingress API and the Gateway +API personas: + +| Ingress API Persona | Gateway API Persona | +|-|-| +| User | Application developer, Application admin, Cluster operator | +| Cluster operator | Cluster operator | +| Infrastructure provider | Infrastructure provider | + +### Available Features + +The Ingress API comes with basic features only: TLS termination and +content-based routing of HTTP traffic based on the host header and the URI of a +request. To offer more features, Ingress controllers support them through +[annotations][anns] on the Ingress resource which are implementation-specific +extensions to the Ingress API. + +[anns]:https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +The annotations approach to extensibility has two negative consequences for +users of the Ingress API: + +* *Limited portability*. Because so many features are available through + annotations, switching between Ingress controllers becomes difficult or even + impossible, as it is necessary to convert the annotations of one + implementation to another (the other implementation might not even support + some features of the first one). This limits the portability of the Ingress + API. +* *Awkwardness of the API*. Because annotations are key-value strings (as + opposed to a structured scheme like the spec of the Ingress resource) and + applied at the top of a resource (rather than in the relevant parts of the + spec), the Ingress API can become awkward to use, especially when a large + number of annotations are added to an Ingress resource. + +Gateway API supports all the features of the Ingress resources and many +features that are only available through annotations. As a result, the Gateway +API is more portable than the Ingress API. Additionally, as the next section +will show, you will not need to use any annotations at all, which addresses the +awkwardness problem. + +### Approach to Extensibility + +The Ingress API has two extensions points: + +* Annotations on the Ingress resource (described in the previous section) +* [Resource backends](https://kubernetes.io/docs/concepts/services-networking/ingress/#resource-backend), + which is the ability to specify a backend other than a Service + +Gateway API is feature-rich compared with the Ingress API. However, to +configure some advanced features like authentication or common but non-portable +across data planes features like connection timeouts and health checks, you will +need to rely on the extensions of Gateway API. + +Gateway API has the following primary extension points: + +* *External references.* A feature (field) of a Gateway API resource can + reference a custom resource specific to the Gateway implementation that + configures that feature. For example: + * [HTTPRouteFilter](../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteFilter) + can reference an external resource via the `extensionRef` field, thus + configuring an implementation-specific filter. + * [BackendObjectReference](../reference/spec.md#gateway.networking.k8s.io/v1.BackendObjectReference) + supports resources other than Services. + * [SecretObjectReference](../reference/spec.md#gateway.networking.k8s.io/v1.SecretObjectReference) + supports resources other than Secrets. +* *Custom implementations*. For some features, it is left up to an + implementation to define how to support them. Those features correspond to the + implementation-specific + (custom) [conformance level](../concepts/conformance.md#2-support-levels). For + example: + * The `RegularExpression` type of + the [HTTPPathMatch](../reference/spec.md#gateway.networking.k8s.io/v1.HTTPPathMatch). +* *Policies.* A Gateway implementation can define custom resources called + Policies for exposing data plane features like authentication. Gateway API + does not prescribe the details of those resources. However, it prescribes a + standard UX. See the [Policy attachment guide](../reference/policy-attachment.md) + for more details. In contrast with the *external references* above, a Gateway + API resource does not reference a Policy. Instead, a Policy must reference a + Gateway API resource. + +The extension points do not include annotations on Gateway API resources. +This approach is strongly discouraged for implementations of the API. + +## Mapping Ingress API features to Gateway API Features + +This section will map the Ingress API features to the corresponding Gateway API +features, covering three major areas: + +* Entry points +* TLS termination +* Routing rules + +### Entry Points + +Roughly speaking, an entry point is a combination of an IP address and port +through which the data plane is accessible to external clients. + +Every Ingress resource has two implicit entry points -- one for HTTP and the +other for HTTPS traffic. An Ingress controller provides those entry points. +Typically, they will either be shared by all Ingress resources, or every Ingress +resource will get dedicated entry points. + +In Gateway API, entry points must be explicitly defined in +a [Gateway](../api-types/gateway.md) resource. For example, if you want the data +plane to handle HTTP traffic on port 80, you need to define +a [listener](../reference/spec.md#gateway.networking.k8s.io/v1.Listener) for +that traffic. Typically, a Gateway implementation provides a dedicated data +plane for each Gateway resource. + +Gateway resources are owned by the cluster operator and the application admin. + +### TLS Termination + +The Ingress resource supports TLS termination via +the [TLS section](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls), +where the TLS certificate and key are stored in a Secret. + +In Gateway API, TLS termination is a property of +the [Gateway listener](../reference/spec.md#gateway.networking.k8s.io/v1.Listener), +and similarly to the Ingress, a TLS certificate and key are also stored in a +Secret. + +Because the listener is part of the Gateway resource, the cluster operator and +application admin own TLS termination. + +### Routing Rules + +The [path-based routing rules](https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types) +of the Ingress resource map directly to +the [routing rules](../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteRule) +of the [HTTPRoute](../api-types/httproute.md). + +The [host-header-based routing rules](https://kubernetes.io/docs/concepts/services-networking/ingress/#name-based-virtual-hosting) +map to +the [hostnames](../reference/spec.md#gateway.networking.k8s.io/v1.Hostname) of +the HTTPRoute. However, note that in the Ingress, each hostname has separate +routing rules, while in the HTTPRoute the routing rules apply to all hostnames. + +> The Ingress API uses the term host while Gateway API uses the hostname. +> This guide will use Gateway API term to refer to the Ingress host. + +> The `hostnames` of an HTTPRoute must match the `hostname` of the [Gateway listener](../reference/spec.md#gateway.networking.k8s.io/v1.Listener). +> Otherwise, the listener will ignore the routing rules for the unmatched +> hostnames. See the [HTTPRoute documentation](../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteSpec). + +HTTPRoutes are owned by the application developer. + +The next three sections map additional features of the Ingress routing rules. + +#### Rules Merging and Conflict Resolution + +Typically, Ingress controllers merge routing rules from all Ingress resources +(unless they provision a data plane per each Ingress resource) and resolve +potential conflicts among the rules. However, both merging and conflict +resolution are not prescribed by the Ingress API, so Ingress controllers might +implement them differently. + +In contrast, Gateway API specifies how to merge rules and resolve conflicts: + +* A Gateway implementation must merge the routing rules from all HTTPRoutes + attached to a listener. +* Conflicts must be handled as + prescribed in [API Design Guide: Conflicts](../guides/api-design.md#conflicts). For example, more specific + matches in a routing rule win over the less specific ones. + +#### Default Backend + +The +Ingress [default backend](https://kubernetes.io/docs/concepts/services-networking/ingress/#default-backend) +configures a backend that will respond to all unmatched HTTP requests related to +that Ingress resource. Gateway API does not have a direct equivalent: it is +necessary to define such a routing rule explicitly. For example, define a rule +to route requests with the path prefix `/` to a Service that corresponds to the +default backend. + +#### Selecting Data Plane to Attach to + +An Ingress resource must specify +a [class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) +to select which Ingress controller to use. An HTTPRoute must specify which +Gateway (or Gateways) to attach to via +a [parentRef](../reference/spec.md#gateway.networking.k8s.io/v1.ParentRef). + +### Implementation-Specific Ingress Features (Annotations) + +Ingress annotations configure implementation-specific features. Thus, converting +them to Gateway API depends both on the Ingress controller and Gateway +implementations. + +Luckily, some of the features supported through annotations are now part of the +Gateway API (HTTPRoute), primarily: + +* Request redirects (including a TLS redirect) +* Request/response manipulation +* Traffic splitting +* Header, query param, or method-based routing + +However, the remaining features remain largely implementation-specific. To +convert them, consult the Gateway implementation documentation to see +which [extension point](#approach-to-extensibility) to use. + +## Example + +This section shows an example of how to convert an Ingress resource to Gateway +API resources. + +### Assumptions + +The example includes the following assumptions: + +* All resources belong to the same namespace. +* The Ingress controller: + * Has the corresponding IngressClass resource `prod` in the cluster. + * Supports the TLS redirect feature via + the `example-ingress-controller.example.org/tls-redirect` annotation. +* The Gateway implementation has the corresponding GatewayClass resource `prod` + in the cluster. + +Additionally, the content of the referenced Secret and Services as well as +IngressClass and GatewayClass are omitted for brevity. + +### Ingress Resource + +The Ingress below defines the following configuration: + +* Configure a TLS redirect for any HTTP request for `foo.example.com` + and `bar.example.com` hostnames using + the `example-ingress-controller.example.org/tls-redirect` annotation. +* Terminate TLS for the `foo.example.com` and `bar.example.com` hostnames using + the TLS certificate and key from the Secret `example-com`. +* Route HTTPS requests for the `foo.example.com` hostname with the URI + prefix `/orders` to the `foo-orders-app` Service. +* Route HTTPS requests for the `foo.example.com` hostname with any other prefix + to the `foo-app` Service. +* Route HTTPS requests for the `bar.example.com` hostname with any URI to + the `bar-app` Service. + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: example-ingress + annotations: + some-ingress-controller.example.org/tls-redirect: "True" +spec: + ingressClassName: prod + tls: + - hosts: + - foo.example.com + - bar.example.com + secretName: example-com + rules: + - host: foo.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: foo-app + port: + number: 80 + - path: /orders + pathType: Prefix + backend: + service: + name: foo-orders-app + port: + number: 80 + - host: bar.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: bar-app + port: + number: 80 +``` + +The next three sections convert that Ingress into Gateway API resources. + +### Conversion Step 1 - Define Gateway + +The following Gateway resource: + +* Belongs to our GatewayClass `prod`. +* Provisions load balancing infrastructure (this depends on the Gateway + implementation). +* Configures HTTP and HTTPS listeners (entry points), which the Ingress resource + included implicitly: + * The HTTP listener `http` on port `80` + * The HTTPS listener `https` on port `443` with TLS termination with the + cert and key stored in the `example-com` Secret, which is the same Secret + used in the Ingress + +Also, note that both listeners allow all HTTPRoutes from the same namespace +(which is the default setting) and restrict HTTPRoute hostnames to +the `example.com` subdomain (allow hostnames like `foo.example.com` but +not `foo.kubernetes.io`). + +```yaml +{% include 'standard/simple-http-https/gateway.yaml' %} +``` + +### Conversion Step 2 - Define HTTPRoutes + +The Ingress is split into two HTTPRoutes -- one for `foo.example.com` and one +for `bar.example.com` hostnames. + +```yaml +{% include 'standard/simple-http-https/foo-route.yaml' %} +``` + +```yaml +{% include 'standard/simple-http-https/bar-route.yaml' %} +``` + +Both HTTPRoutes: + +* Attach to the `https` listener of the Gateway resource from Step 1. +* Define the same routing rules as in the Ingress rules for the corresponding + hostname. + +### Step 3 - Configure TLS Redirect + +The following HTTPRoute configures a TLS redirect, which the Ingress resource +configured via an annotation. The HTTPRoute below: + +* Attaches to the `http` listener of our Gateway. +* Issues a TLS redirect for any HTTP request for the `foo.example.com` + or `bar.example.com` hostnames. + +```yaml +{% include 'standard/simple-http-https/tls-redirect-route.yaml' %} +``` + +## Automatic Conversion of Ingresses + +The [Ingress to Gateway](https://github.com/kubernetes-sigs/ingress2gateway) +project helps translate Ingress resources to Gateway API resources, specifically +HTTPRoutes. The conversion results should always be tested and verified. diff --git a/site-src/ko/guides/multiple-ns.md b/site-src/ko/guides/multiple-ns.md new file mode 100644 index 0000000000..6805f2c5d1 --- /dev/null +++ b/site-src/ko/guides/multiple-ns.md @@ -0,0 +1,169 @@ +# Cross-Namespace routing + +Gateway API has core support for cross Namespace routing. This is useful +when more than one user or team is sharing the underlying networking +infrastructure, yet control and configuration must be segmented to minimize +access and fault domains. + +Gateways and Routes can be deployed into different Namespaces and Routes can +attach to Gateways across Namespace boundaries. This allows user access +control to be applied differently across Namespaces for Routes and Gateways, +effectively segmenting access and control to different parts of the +cluster-wide routing configuration. The ability for Routes to attach to +Gateways across Namespace boundaries are governed by [_Route Attachment_](#cross-namespace-route-attachment). Route attachment is explored +in this guide and demonstrates how independent teams can safely share the same +Gateway. + +In this guide there are two independent teams, _store_ and _site_, operating +in the same Kubernetes cluster in the `store-ns` and `site-ns` Namespaces. These +are their goals and how they use Gateway API resources to accomplish them: + +- The site team has two applications, _home_ and _login_. The team wants to to +isolate access and configuration across their apps as much as possible to +minimize access and failure domains. They use separate HTTPRoutes attached to +the same Gateway to isolate routing configurations, such as canary rollouts, +but still share the same IP address, port, DNS domain, and TLS certificate. +- The store team has a single Service called _store_ that they have deployed +in the `store-ns` Namespace which also needs to be exposed behind the same IP +address and domain. +- The Foobar Corporation operates behind the `foo.example.com` domain for all +apps. This is controlled by a central infrastructure team, operating in the +`infra-ns` Namespace. +- Lastly, the security team controls the certificate for `foo.example.com`. +By managing this certificate through the single shared Gateway they are able +to centrally control security without directly involving application teams. + +The logical relationship between Gateway API resources looks like this: + +![Cross-Namespace routing](../images/cross-namespace-routing.svg) + +## Cross-namespace Route Attachment + +[Route attachment][attachment] is an important concept that dictates how Routes +attach to Gateways and program their routing rules. It is especially relevant +when there are Routes across Namespaces that share one or more Gateways. +Gateway and Route attachment is bidirectional - attachment can only succeed if +the Gateway owner and Route owner both agree to the relationship. This +bi-directional relationship exists for two reasons: + +- Route owners don't want to overexpose their applications through paths they +are not aware of. +- Gateway owners don't want certain apps or teams using Gateways without +permission. For example, an internal service shouldn't be accessible +through an internet Gateway. + +Gateways support _attachment constraints_ which are fields on Gateway +listeners that restrict which Routes can be attached. Gateways support +Namespaces and Route types as attachment constraints. Any Routes that do not +meet the attachment constraints are not able to attach to that Gateway. +Similarly, Routes explicitly reference Gateways that they want to attach to +through the Route's `parentRef` field. Together these create a handshake +between the infra owners and application owners that enables them to +independently define how applications are exposed through Gateways. This is +effectively a policy that reduces administrative overhead. App owners can +specify which Gateways their apps should use and infra owners can constrain +the Namespaces and types of Routes that a Gateway accepts. + + +## Shared Gateway + +The infrastructure team deploys the `shared-gateway` Gateway into the `infra-ns` +Namespace: + +```yaml +{% include 'standard/cross-namespace-routing/gateway.yaml' %} +``` + +The `https` listener in the above Gateway matches traffic for the +`foo.example.com` domain. This allows the infrastructure team to manage all +aspects of the domain. The HTTPRoutes below do not need to specify domains +and will match all traffic by default if `hostname` is not set. This makes +it easier to manage HTTPRoutes because they can be domain agnostic, which is +helpful when application domains are not static. + +This Gateway also configures HTTPS using the `foo-example-com` Secret +in the `infra-ns` Namespace. This allows the infrastructure team to centrally +manage TLS on behalf of app owners. The `foo-example-com` certificate will +terminate all traffic going to its attached Routes, without any TLS +configuration on the HTTPRoutes themselves. + +This Gateway uses a Namespace selector to define which HTTPRoutes are allowed +to attach. This allows the infrastructure team to constrain who +or which apps can use this Gateway by allowlisting a set of Namespaces. + + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +spec: + listeners: + - allowedRoutes: + namespaces: + from: Selector + selector: + matchLabels: + shared-gateway-access: "true" +... +``` + +_Only_ Namespaces which are labelled `shared-gateway-access: "true"` will be +able to attach their Routes to `shared-gateway`. In the following set of +Namespaces, if an HTTPRoute existed in the `no-external-access` Namespace with +a `parentRef` for `infra-ns/shared-gateway`, it would be ignored by the +Gateway because the attachment constraint (Namespace label) was not met. + +```yaml +{% include 'standard/cross-namespace-routing/0-namespaces.yaml' %} +``` + +Note that attachment constraints on the Gateway are not required, but they are +a best-practice if operating a cluster with many different teams and +Namespaces. In environments where all apps in a cluster have permission to +attach to a Gateway then the `listeners[].routes` field does not have to be +configured and all Routes can freely use the Gateway. + + +## Route Attachment + +The store team deploys their route for the `store` Service in the `store-ns` +Namespace: + +```yaml +{% include 'standard/cross-namespace-routing/store-route.yaml' %} +``` + +This Route has straightforward routing logic as it just matches for +`/store` traffic which it sends to the `store` Service. + +The site team now deploys Routes for their applications. They deploy two +HTTPRoutes into the `site-ns` Namespace: + +- The `home` HTTPRoute acts as a default routing rule, matching for all traffic +to `foo.example.com/*` not matched by an existing routing rule and sending it to +the `home` Service. +- The `login` HTTPRoute routes traffic for `foo.example.com/login` to +`service/login-v1` and `service/login-v2`. It uses weights to granularly +control traffic distribution between them. + +Both of these Routes use the same Gateway attachment configuration which +specifies `gateway/shared-gateway` in the `infra-ns` Namespace as the only +Gateway that these Routes want to attach to. + +```yaml +{% include 'standard/cross-namespace-routing/site-route.yaml' %} +``` + +After these three Routes are deployed, they will all be attached to the +`shared-gateway` Gateway. The Gateway merges these Routes into a single flat +list of routing rules. [Routing precedence](../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteRule) +between these routing rules is determined by most specific match and +conflicts are handled according to [conflict +resolution](api-design.md#conflicts). This provides predictable and +deterministic merging of routing rules between independent users. + +Thanks to cross-Namespace routing, the Foobar Corporation can distribute +ownership of their infrastructure more evenly, while still retaining centralized +control. This gives them the best of both worlds, all delivered through +declarative and open source APIs. + +[attachment]:../concepts/api-overview.md#attaching-routes-to-gateways diff --git a/site-src/ko/guides/simple-gateway.md b/site-src/ko/guides/simple-gateway.md new file mode 100644 index 0000000000..bcfd64ab04 --- /dev/null +++ b/site-src/ko/guides/simple-gateway.md @@ -0,0 +1,47 @@ +# Deploying a simple Gateway + + +The simplest possible deployment is a Gateway and Route resource which are +deployed together by the same owner. This represents a similar kind of model +used for Ingress. In this guide, a Gateway and HTTPRoute are deployed which +match all HTTP traffic and directs it to a single Service named `foo-svc`. + +![Simple Gateway](../images/single-service-gateway.png) + +```yaml +{% include 'standard/simple-gateway/gateway.yaml' %} +``` + +The Gateway represents the instantiation of a logical load balancer and the +GatewayClass defines the load balancer template when users create a Gateway. +The example Gateway is templated from a hypothetical `example` +GatewayClass, which is meant to be a placeholder and substituted by users. Here +is a list of available +[Gateway Implementation](../implementations.md) that +can be used to determine the correct GatewayClass based on the specific +infrastructure provider. + +The Gateway listens for HTTP traffic on port 80. This particular GatewayClass +automatically assigns an IP address which will be shown in the `Gateway.status` +after it has been deployed. + +Route resources specify the Gateways they want to attach to using `ParentRefs`. As long as +the Gateway allows this attachment (by default Routes from the same namespace are trusted), +this will allow the Route to receive traffic from the parent Gateway. +`BackendRefs` define the backends that traffic will be sent to. More complex +bi-directional matching and permissions are possible and explained in other guides. + +The following HTTPRoute defines how traffic from the Gateway listener is routed +to backends. Because there are no host routes or paths specified, this HTTPRoute +will match all HTTP traffic that arrives at port 80 of the load balancer and +send it to the `foo-svc` Pods. + +```yaml +{% include 'standard/simple-gateway/httproute.yaml' %} +``` + +While Route resources are often used to filter traffic to many different +backends (potentially with different owners), this demonstrates the simplest +possible route with a single Service backend. This example shows how a service +owner can deploy both the Gateway and the HTTPRoute for their usage alone, +giving them more control and autonomy for how the service is exposed. diff --git a/site-src/ko/guides/tcp.md b/site-src/ko/guides/tcp.md new file mode 100644 index 0000000000..ccd460aeb9 --- /dev/null +++ b/site-src/ko/guides/tcp.md @@ -0,0 +1,72 @@ +!!! info "Experimental Channel" + + The `TCPRoute` resource described below is currently only included in the + "Experimental" channel of Gateway API. For more information on release + channels, refer to our [versioning guide](../concepts/versioning.md). + +Gateway API is designed to work with multiple protocols and [TCPRoute][tcproute] +is one such route which allows for managing [TCP][tcp] traffic. + +In this example, we have one Gateway resource and two TCPRoute resources that +distribute the traffic with the following rules: + +- All TCP streams on port 8080 of the Gateway are forwarded to port 6000 of + `my-foo-service` Kubernetes Service. +- All TCP streams on port 8090 of the Gateway are forwarded to port 6000 of + `my-bar-service` Kubernetes Service. + +In this example two `TCP` listeners will be applied to the [Gateway][gateway] +in order to route them to two separate backend `TCPRoutes`, note that the +`protocol` set for the `listeners` on the `Gateway` is `TCP`: + +```yaml +{% include 'experimental/basic-tcp.yaml' %} +``` + +In the above example we separate the traffic for the two separate backend TCP +[Services][svc] by using the `sectionName` field in the `parentRefs`: + +```yaml +spec: + parentRefs: + - name: my-tcp-gateway + sectionName: foo +``` + +This corresponds directly with the `name` in the `listeners` in the `Gateway`: + +```yaml + listeners: + - name: foo + protocol: TCP + port: 8080 + - name: bar + protocol: TCP + port: 8090 +``` + +In this way each `TCPRoute` "attaches" itself to a different port on the +`Gateway` so that the service `my-foo-service` is taking traffic for port `8080` +from outside the cluster and `my-bar-service` takes the port `8090` traffic. + +Note that you can achieve this same result by binding the Routes to the Gateway +listeners using the `port` field in the `parentRefs`: + +```yaml +spec: + parentRefs: + - name: my-tcp-gateway + port: 8080 +``` + +Using the `port` field instead of `sectionName` for the attachment has the +downside of more tightly coupling the relationship between the Gateway and +its associated Routes. Refer to [Attaching to Gateways][attaching] for more +details. + +[tcproute]:../reference/spec.md#gateway.networking.k8s.io/v1alpha2.TCPRoute +[tcp]:https://datatracker.ietf.org/doc/html/rfc793 +[httproute]:../reference/spec.md#gateway.networking.k8s.io/v1alpha2.HTTPRoute +[gateway]:../reference/spec.md#gateway.networking.k8s.io/v1alpha2.Gateway +[svc]:https://kubernetes.io/docs/concepts/services-networking/service/ +[attaching]:../api-types/httproute.md#attaching-to-gateways diff --git a/site-src/ko/guides/tls.md b/site-src/ko/guides/tls.md new file mode 100644 index 0000000000..be3281ee8a --- /dev/null +++ b/site-src/ko/guides/tls.md @@ -0,0 +1,165 @@ +# TLS Configuration + +Gateway API allows for a variety of ways to configure TLS. This document lays +out various TLS settings and gives general guidelines on how to use them +effectively. + +Although this doc covers the most common forms of TLS configuration with Gateway +API, some implementations may also offer implementation-specific extensions that +allow for different or more advanced forms of TLS configuration. In addition to +this documentation, it's worth reading the TLS documentation for whichever +implementation(s) you're using with Gateway API. + +!!! info "Experimental Channel" + + The `TLSRoute` and `BackendTLSPolicy` resources described below are currently only included in the + "Experimental" channel of Gateway API. For more information on release + channels, refer to our [versioning guide](../concepts/versioning.md). + +## Client/Server and TLS + +![overview](../images/tls-overview.svg) + +For Gateways, there are two connections involved: + +- **downstream**: This is the connection between the client and the Gateway. +- **upstream**: This is the connection between the Gateway and backend resources + specified by routes. These backend resources will usually be Services. + +With Gateway API, TLS configuration of downstream and +upstream connections is managed independently. + +For downstream connections, depending on the Listener Protocol, different TLS modes and Route types are supported. + +| Listener Protocol | TLS Mode | Route Type Supported | +|-------------------|-------------|---------------------| +| TLS | Passthrough | TLSRoute | +| TLS | Terminate | TCPRoute | +| HTTPS | Terminate | HTTPRoute | +| GRPC | Terminate | GRPCRoute | + +Please note that in case of `Passthrough` TLS mode, no TLS settings take +effect as the TLS session from the client is NOT terminated at the Gateway, but rather +passes through the Gateway, encrypted. + +For upstream connections, `BackendTLSPolicy` is used, and neither listener protocol nor TLS mode apply to the +upstream TLS configuration. For `HTTPRoute`, the use of both `Terminate` TLS mode and `BackendTLSPolicy` is supported. +Using these together provides what is commonly known as a connection that is terminated and then re-encrypted at +the Gateway. + +## Downstream TLS + +Downstream TLS settings are configured using listeners at the Gateway level. + +### Listeners and TLS + +Listeners expose the TLS setting on a per domain or subdomain basis. +TLS settings of a listener are applied to all domains that satisfy the +`hostname` criteria. + +In the following example, the Gateway serves the TLS certificate +defined in the `default-cert` Secret resource for all requests. +Although the example refers to HTTPS protocol, one can also use the same +feature for TLS-only protocol along with TLSRoutes. + +```yaml +listeners: +- protocol: HTTPS # Other possible value is `TLS` + port: 443 + tls: + mode: Terminate # If protocol is `TLS`, `Passthrough` is a possible mode + certificateRefs: + - kind: Secret + group: "" + name: default-cert +``` + +### Examples + +#### Listeners with different certificates + +In this example, the Gateway is configured to serve the `foo.example.com` and +`bar.example.com` domains. The certificate for these domains is specified +in the Gateway. + +```yaml +{% include 'standard/tls-basic.yaml' %} +``` + +#### Wildcard TLS listeners + +In this example, the Gateway is configured with a wildcard certificate for +`*.example.com` and a different certificate for `foo.example.com`. +Since a specific match takes priority, the Gateway will serve +`foo-example-com-cert` for requests to `foo.example.com` and +`wildcard-example-com-cert` for all other requests. + +```yaml +{% include 'standard/wildcard-tls-gateway.yaml' %} +``` + +#### Cross namespace certificate references + +In this example, the Gateway is configured to reference a certificate in a +different namespace. This is allowed by the ReferenceGrant created in the +target namespace. Without that ReferenceGrant, the cross-namespace reference +would be invalid. + +```yaml +{% include 'standard/tls-cert-cross-namespace.yaml' %} +``` + +## Upstream TLS + +Upstream TLS settings are configured using the experimental `BackendTLSPolicy` +attached to a `Service` via a target reference. + +This resource can be used to describe the SNI the Gateway should use to connect to the +backend and how the certificate served by the backend Pod(s) should be verified. + +### TargetRefs and TLS + +BackendTLSPolicy contains specification for the `TargetRefs` and `Validation`. TargetRefs is required and +identifies one or more `Service`s for which your HTTPRoute requires TLS. The `Validation` configuration contains a +required `Hostname`, and either `CACertificateRefs` or `WellKnownCACertificates`. + +Hostname refers to the SNI the Gateway should use to connect to the backend, and +must match the certificate served by the backend pod. + +CACertificateRefs refer to one or more PEM-encoded TLS certificates. If there are no specific certificates +to use, then you must set WellKnownCACertificates to "System" to tell the Gateway to use a set of trusted +CA Certificates. There may be some variation in which system certificates are used by each implementation. +Refer to documentation from your implementation of choice for more information. + +!!! info "Restrictions" + + - Cross-namespace certificate references are not allowed. + - Wildcard hostnames are not allowed. + +### Examples + +#### Using System Certificates + +In this example, the `BackendTLSPolicy` is configured to use system certificates to connect with a +TLS-encrypted upstream connection where Pods backing the `dev` Service are expected to serve a valid +certificate for `dev.example.com`. + +```yaml +{% include 'experimental/v1alpha3/backendtlspolicy-system-certs.yaml' %} +``` + +#### Using Explicit CA Certificates + +In this example, the `BackendTLSPolicy` is configured to use certificates defined in the configuration +map `auth-cert` to connect with a TLS-encrypted upstream connection where Pods backing the `auth` Service +are expected to serve a valid certificate for `auth.example.com`. + +```yaml +{% include 'experimental/v1alpha3/backendtlspolicy-ca-certs.yaml' %} +``` + +## Extensions + +Gateway TLS configurations provides an `options` map to add additional TLS +settings for implementation-specific features. Some examples of features that +could go in here would be TLS version restrictions, or ciphers to use. diff --git a/site-src/ko/guides/traffic-splitting.md b/site-src/ko/guides/traffic-splitting.md new file mode 100644 index 0000000000..b2f9968268 --- /dev/null +++ b/site-src/ko/guides/traffic-splitting.md @@ -0,0 +1,87 @@ +# HTTP traffic splitting + +The [HTTPRoute resource](../api-types/httproute.md) allows you to specify +weights to shift traffic between different backends. This is useful for +splitting traffic during rollouts, canarying changes, or for emergencies. +The HTTPRoute`spec.rules.backendRefs` accepts a list of backends that a route +rule will send traffic to. The relative weights of these backends define +the split of traffic between them. The following YAML snippet shows how two +Services are listed as backends for a single route rule. This route rule +will split traffic 90% to `foo-v1` and 10% to `foo-v2`. + +![Traffic splitting](../images/simple-split.png) + +```yaml +{% include 'standard/traffic-splitting/simple-split.yaml' %} +``` + +`weight` indicates a proportional split of traffic (rather than percentage) +and so the sum of all the weights within a single route rule is the +denominator for all of the backends. `weight` is an optional parameter and if +not specified, defaults to 1. If only a single backend is specified for a +route rule it implicitly receives 100% of the traffic, no matter what (if any) +weight is specified. + +## Guide + +This guide shows the deployment of two versions of a Service. Traffic splitting +is used to manage the gradual splitting of traffic from v1 to v2. + +This example assumes that the following Gateway is deployed: + +```yaml +{% include 'standard/simple-gateway/gateway.yaml' %} +``` + +## Canary traffic rollout + +At first, there may only be a single version of a Service that serves +production user traffic for `foo.example.com`. The following HTTPRoute has no +`weight` specified for `foo-v1` or `foo-v2` so they will implicitly +receive 100% of the traffic matched by each of their route rules. A canary +route rule is used (matching the header `traffic=test`) to send synthetic test +traffic before splitting any production user traffic to `foo-v2`. +[Routing precedence](../reference/spec.md#gateway.networking.k8s.io/v1.HTTPRouteRule) +ensures that all traffic with the matching host and header +(the most specific match) will be sent to `foo-v2`. + +![Traffic splitting](../images/traffic-splitting-1.png) + + +```yaml +{% include 'standard/traffic-splitting/traffic-split-1.yaml' %} +``` + +## Blue-green traffic rollout + +After internal testing has validated successful responses from `foo-v2`, +it's desirable to shift a small percentage of the traffic to the new Service +for gradual and more realistic testing. The HTTPRoute below adds `foo-v2` +as a backend along with weights. The weights add up to a total of 100 so +`foo-v1` receives 90/100=90% of the traffic and `foo-v2` receives +10/100=10% of the traffic. + +![Traffic splitting](../images/traffic-splitting-2.png) + + +```yaml +{% include 'standard/traffic-splitting/traffic-split-2.yaml' %} +``` + +## Completing the rollout + +Finally, if all signals are positive, it is time to fully shift traffic to +`foo-v2` and complete the rollout. The weight for `foo-v1` is set to +`0` so that it is configured to accept zero traffic. + +![Traffic splitting](../images/traffic-splitting-3.png) + + +```yaml +{% include 'standard/traffic-splitting/traffic-split-3.yaml' %} +``` + +At this point 100% of the traffic is being routed to `foo-v2` and the +rollout is complete. If for any reason `foo-v2` experiences errors, the +weights can be updated to quickly shift traffic back to `foo-v1`. Once +the rollout is deemed final, v1 can be fully decommissioned. diff --git a/site-src/ko/images/api-model.png b/site-src/ko/images/api-model.png new file mode 100644 index 0000000000..1a01ac5f6c Binary files /dev/null and b/site-src/ko/images/api-model.png differ diff --git a/site-src/ko/images/backendtlspolicy-api.png b/site-src/ko/images/backendtlspolicy-api.png new file mode 100644 index 0000000000..af9f442c3a Binary files /dev/null and b/site-src/ko/images/backendtlspolicy-api.png differ diff --git a/site-src/ko/images/cross-namespace-routing.svg b/site-src/ko/images/cross-namespace-routing.svg new file mode 100644 index 0000000000..3bc429e3eb --- /dev/null +++ b/site-src/ko/images/cross-namespace-routing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site-src/ko/images/gateway-roles.png b/site-src/ko/images/gateway-roles.png new file mode 100644 index 0000000000..4848bfa20f Binary files /dev/null and b/site-src/ko/images/gateway-roles.png differ diff --git a/site-src/ko/images/gateway-route-binding.png b/site-src/ko/images/gateway-route-binding.png new file mode 100644 index 0000000000..a62baf7324 Binary files /dev/null and b/site-src/ko/images/gateway-route-binding.png differ diff --git a/site-src/ko/images/grpc-routing.png b/site-src/ko/images/grpc-routing.png new file mode 100644 index 0000000000..525f5ce1f4 Binary files /dev/null and b/site-src/ko/images/grpc-routing.png differ diff --git a/site-src/ko/images/grpc-routing.svg b/site-src/ko/images/grpc-routing.svg new file mode 100644 index 0000000000..48473aed8c --- /dev/null +++ b/site-src/ko/images/grpc-routing.svg @@ -0,0 +1,655 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +Load BalancerGateway +prodGRPCRoute +bar-routefoo.example.comcom.example.User.LoginServicebar-svc-canaryPodPodPodGRPCRoute +foo-routeServicefoo-svcServicebar-svcbar.example.combar.example.comenv: canary diff --git a/site-src/ko/images/grpcroute-basic-example.png b/site-src/ko/images/grpcroute-basic-example.png new file mode 100644 index 0000000000..8db9b52fdd Binary files /dev/null and b/site-src/ko/images/grpcroute-basic-example.png differ diff --git a/site-src/ko/images/grpcroute-basic-example.svg b/site-src/ko/images/grpcroute-basic-example.svg new file mode 100644 index 0000000000..5311ba0330 --- /dev/null +++ b/site-src/ko/images/grpcroute-basic-example.svg @@ -0,0 +1,851 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gRPC + GRPCRoute + diff --git a/site-src/ko/images/http-routing.png b/site-src/ko/images/http-routing.png new file mode 100644 index 0000000000..3b9e417bc6 Binary files /dev/null and b/site-src/ko/images/http-routing.png differ diff --git a/site-src/ko/images/httproute-basic-example.svg b/site-src/ko/images/httproute-basic-example.svg new file mode 100644 index 0000000000..a02852868b --- /dev/null +++ b/site-src/ko/images/httproute-basic-example.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site-src/ko/images/httproute-with-backend-tls-policy.png b/site-src/ko/images/httproute-with-backend-tls-policy.png new file mode 100644 index 0000000000..fda4088db3 Binary files /dev/null and b/site-src/ko/images/httproute-with-backend-tls-policy.png differ diff --git a/site-src/ko/images/k8s-favicon.png b/site-src/ko/images/k8s-favicon.png new file mode 100644 index 0000000000..ef16534233 Binary files /dev/null and b/site-src/ko/images/k8s-favicon.png differ diff --git a/site-src/ko/images/lifecycle-new-fields.svg b/site-src/ko/images/lifecycle-new-fields.svg new file mode 100644 index 0000000000..46f265f088 --- /dev/null +++ b/site-src/ko/images/lifecycle-new-fields.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site-src/ko/images/lifecycle-new-resources.png b/site-src/ko/images/lifecycle-new-resources.png new file mode 100644 index 0000000000..27f80bb24d Binary files /dev/null and b/site-src/ko/images/lifecycle-new-resources.png differ diff --git a/site-src/ko/images/logo/logo-text-horizontal-white.png b/site-src/ko/images/logo/logo-text-horizontal-white.png new file mode 100644 index 0000000000..4f9ecce302 Binary files /dev/null and b/site-src/ko/images/logo/logo-text-horizontal-white.png differ diff --git a/site-src/ko/images/logo/logo-text-horizontal.png b/site-src/ko/images/logo/logo-text-horizontal.png new file mode 100644 index 0000000000..83826417f6 Binary files /dev/null and b/site-src/ko/images/logo/logo-text-horizontal.png differ diff --git a/site-src/ko/images/logo/logo-text-horizontal.svg b/site-src/ko/images/logo/logo-text-horizontal.svg new file mode 100644 index 0000000000..9bfa922940 --- /dev/null +++ b/site-src/ko/images/logo/logo-text-horizontal.svg @@ -0,0 +1,205 @@ + + gateway api diff --git a/site-src/ko/images/logo/logo-text-large-horizontal-white.png b/site-src/ko/images/logo/logo-text-large-horizontal-white.png new file mode 100644 index 0000000000..7944032e98 Binary files /dev/null and b/site-src/ko/images/logo/logo-text-large-horizontal-white.png differ diff --git a/site-src/ko/images/logo/logo-text-large-horizontal-white.svg b/site-src/ko/images/logo/logo-text-large-horizontal-white.svg new file mode 100644 index 0000000000..095ef08a1f --- /dev/null +++ b/site-src/ko/images/logo/logo-text-large-horizontal-white.svg @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + gateway api diff --git a/site-src/ko/images/logo/logo.svg b/site-src/ko/images/logo/logo.svg new file mode 100644 index 0000000000..da33c5a239 --- /dev/null +++ b/site-src/ko/images/logo/logo.svg @@ -0,0 +1,188 @@ + + diff --git a/site-src/ko/images/logo/origin/logo-text-horizontal-white.png b/site-src/ko/images/logo/origin/logo-text-horizontal-white.png new file mode 100644 index 0000000000..891ffff571 Binary files /dev/null and b/site-src/ko/images/logo/origin/logo-text-horizontal-white.png differ diff --git a/site-src/ko/images/logo/origin/logo-text-horizontal.png b/site-src/ko/images/logo/origin/logo-text-horizontal.png new file mode 100644 index 0000000000..5a2215397f Binary files /dev/null and b/site-src/ko/images/logo/origin/logo-text-horizontal.png differ diff --git a/site-src/ko/images/logo/origin/logo-text-horizontal.svg b/site-src/ko/images/logo/origin/logo-text-horizontal.svg new file mode 100644 index 0000000000..9bfa922940 --- /dev/null +++ b/site-src/ko/images/logo/origin/logo-text-horizontal.svg @@ -0,0 +1,205 @@ + + gateway api diff --git a/site-src/ko/images/logo/origin/logo-text-large-horizontal-white.png b/site-src/ko/images/logo/origin/logo-text-large-horizontal-white.png new file mode 100644 index 0000000000..7e43b1ae22 Binary files /dev/null and b/site-src/ko/images/logo/origin/logo-text-large-horizontal-white.png differ diff --git a/site-src/ko/images/logo/origin/logo-text-large-horizontal-white.svg b/site-src/ko/images/logo/origin/logo-text-large-horizontal-white.svg new file mode 100644 index 0000000000..095ef08a1f --- /dev/null +++ b/site-src/ko/images/logo/origin/logo-text-large-horizontal-white.svg @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + gateway api diff --git a/site-src/ko/images/logo/origin/logo.svg b/site-src/ko/images/logo/origin/logo.svg new file mode 100644 index 0000000000..da33c5a239 --- /dev/null +++ b/site-src/ko/images/logo/origin/logo.svg @@ -0,0 +1,188 @@ + + diff --git a/site-src/ko/images/policy/hierarchy.png b/site-src/ko/images/policy/hierarchy.png new file mode 100644 index 0000000000..7b5f64d47d Binary files /dev/null and b/site-src/ko/images/policy/hierarchy.png differ diff --git a/site-src/ko/images/policy/ingress-attachment.png b/site-src/ko/images/policy/ingress-attachment.png new file mode 100644 index 0000000000..dbd4035aab Binary files /dev/null and b/site-src/ko/images/policy/ingress-attachment.png differ diff --git a/site-src/ko/images/policy/ingress-complex.png b/site-src/ko/images/policy/ingress-complex.png new file mode 100644 index 0000000000..28d5ab0f82 Binary files /dev/null and b/site-src/ko/images/policy/ingress-complex.png differ diff --git a/site-src/ko/images/policy/ingress-simple.png b/site-src/ko/images/policy/ingress-simple.png new file mode 100644 index 0000000000..88f3e0910b Binary files /dev/null and b/site-src/ko/images/policy/ingress-simple.png differ diff --git a/site-src/ko/images/policy/mesh-complex.png b/site-src/ko/images/policy/mesh-complex.png new file mode 100644 index 0000000000..c1a12fd36b Binary files /dev/null and b/site-src/ko/images/policy/mesh-complex.png differ diff --git a/site-src/ko/images/policy/mesh-simple.png b/site-src/ko/images/policy/mesh-simple.png new file mode 100644 index 0000000000..5ab39b567a Binary files /dev/null and b/site-src/ko/images/policy/mesh-simple.png differ diff --git a/site-src/ko/images/referencegrant-simple.svg b/site-src/ko/images/referencegrant-simple.svg new file mode 100644 index 0000000000..0f3a6f8598 --- /dev/null +++ b/site-src/ko/images/referencegrant-simple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site-src/ko/images/release-channel-overlap.svg b/site-src/ko/images/release-channel-overlap.svg new file mode 100644 index 0000000000..57a7a0a44e --- /dev/null +++ b/site-src/ko/images/release-channel-overlap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site-src/ko/images/resource-model.png b/site-src/ko/images/resource-model.png new file mode 100644 index 0000000000..0397ad2698 Binary files /dev/null and b/site-src/ko/images/resource-model.png differ diff --git a/site-src/ko/images/schema-uml.svg b/site-src/ko/images/schema-uml.svg new file mode 100644 index 0000000000..11e1e29519 --- /dev/null +++ b/site-src/ko/images/schema-uml.svg @@ -0,0 +1,275 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/site-src/ko/images/simple-split.png b/site-src/ko/images/simple-split.png new file mode 100644 index 0000000000..dba5ac4963 Binary files /dev/null and b/site-src/ko/images/simple-split.png differ diff --git a/site-src/ko/images/single-service-gateway.png b/site-src/ko/images/single-service-gateway.png new file mode 100644 index 0000000000..b0095d117c Binary files /dev/null and b/site-src/ko/images/single-service-gateway.png differ diff --git a/site-src/ko/images/tls-overview.svg b/site-src/ko/images/tls-overview.svg new file mode 100644 index 0000000000..8b9e286155 --- /dev/null +++ b/site-src/ko/images/tls-overview.svg @@ -0,0 +1,3 @@ + + +
Gateway
Gateway
Client
Client
Service
Service
Downstream
Downst...
Upstream
Upstre...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/site-src/ko/images/tls-termination-types.png b/site-src/ko/images/tls-termination-types.png new file mode 100644 index 0000000000..53e258ff78 Binary files /dev/null and b/site-src/ko/images/tls-termination-types.png differ diff --git a/site-src/ko/images/traffic-splitting-1.png b/site-src/ko/images/traffic-splitting-1.png new file mode 100644 index 0000000000..0875d72b5f Binary files /dev/null and b/site-src/ko/images/traffic-splitting-1.png differ diff --git a/site-src/ko/images/traffic-splitting-2.png b/site-src/ko/images/traffic-splitting-2.png new file mode 100644 index 0000000000..aefb6ca39e Binary files /dev/null and b/site-src/ko/images/traffic-splitting-2.png differ diff --git a/site-src/ko/images/traffic-splitting-3.png b/site-src/ko/images/traffic-splitting-3.png new file mode 100644 index 0000000000..22501cde1a Binary files /dev/null and b/site-src/ko/images/traffic-splitting-3.png differ diff --git a/site-src/ko/images/v1alpha2-group.png b/site-src/ko/images/v1alpha2-group.png new file mode 100644 index 0000000000..4b77553bb4 Binary files /dev/null and b/site-src/ko/images/v1alpha2-group.png differ diff --git a/site-src/ko/implementations.md b/site-src/ko/implementations.md new file mode 100644 index 0000000000..2e5204af48 --- /dev/null +++ b/site-src/ko/implementations.md @@ -0,0 +1,611 @@ +# 구현체 + +이 문서는 게이트웨이 API의 다운스트림 구현 및 통합을 추적하고 +이들에 대한 상태 및 리소스 참조를 제공한다. + +게이트웨이 API의 구현자와 통합자들은 자신들의 구현체에 대한 상태 정보, 지원하는 버전, 그리고 +사용자가 시작하는 데 도움이 되는 문서를, 이 문서에 업데이트하는 것이 +권장된다. + + +!!! info "구현체 간 확장 지원 기능 비교" + + [프로젝트의 지원 기능을 빠르게 비교할 수 있는 표 확인](implementations/v1.3.md). 표는 코어 호환성 테스트를 통과한 게이트웨이 컨트롤러 구현체를 개요로 제시하며, 구현한 확장 호환성 기능에 초점을 맞춘다. + +## 게이트웨이 컨트롤러 구현 상태 + +- [Acnodal EPIC][1] +- [Airlock Microgateway][34] +- [Amazon Elastic Kubernetes Service][23] (GA) +- [Apache APISIX][2] (beta) +- [Avi Kubernetes Operator][31] +- [Azure Application Gateway for Containers][27] (GA) +- [Cilium][16] (beta) +- [Contour][3] (GA) +- [Easegress][30] (GA) +- [Emissary-Ingress (Ambassador API Gateway)][4] (alpha) +- [Envoy Gateway][18] (GA) +- [Flomesh Service Mesh][17] (beta) +- [Gloo Gateway][5] (GA) +- [Google Kubernetes Engine][6] (GA) +- [HAProxy Ingress][7] (alpha) +- [HAProxy Kubernetes Ingress Controller][32] (GA) +- [HashiCorp Consul][8] +- [Istio][9] (GA) +- [kgateway][37] (GA) +- [Kong Ingress Controller][10] (GA) +- [Kong Gateway Operator][35] (GA) +* [Kubvernor][39](진행 중) +- [Kuma][11] (GA) +- [LiteSpeed Ingress Controller][19] +- [LoxiLB][36] (beta) +- [NGINX Gateway Fabric][12] (GA) +- [ngrok][33] (preview) +- [STUNner][21] (beta) +- [Traefik Proxy][13] (GA) +- [Tyk][29] (진행 중) +- [WSO2 APK][25] (GA) + +## 서비스 메시 구현 상태 + +- [Google Cloud Service Mesh][38] (GA) +- [Istio][9] (GA) +- [Kuma][11] (GA) +- [Linkerd][28] (GA) + +## 통합 + +- [Flagger][14] (public preview) +- [cert-manager][15] (alpha) +- [argo-rollouts][22] (alpha) +- [Knative][24] (alpha) +- [Kuadrant][26] (GA) + +[1]:#acnodal-epic +[2]:#apisix +[3]:#contour +[4]:#emissary-ingress-ambassador-api-gateway +[5]:#gloo-gateway +[6]:#google-kubernetes-engine +[7]:#haproxy-ingress +[8]:#hashicorp-consul +[9]:#istio +[10]:#kong-kubernetes-ingress-controller +[11]:#kuma +[12]:#nginx-gateway-fabric +[13]:#traefik-proxy +[14]:#flagger +[15]:#cert-manager +[16]:#cilium +[17]:#flomesh-service-mesh-fsm +[18]:#envoy-gateway +[19]:#litespeed-ingress-controller +[21]:#stunner +[22]:#argo-rollouts +[23]:#amazon-elastic-kubernetes-service +[24]:#knative +[25]:#wso2-apk +[26]:#kuadrant +[27]:#azure-application-gateway-for-containers +[28]:#linkerd +[29]:#tyk +[30]:#easegress +[31]:#avi-kubernetes-operator +[32]:#haproxy-kubernetes-ingress-controller +[33]:#ngrok-kubernetes-operator +[34]:#airlock-microgateway +[35]:#kong-gateway-operator +[36]:#loxilb +[37]:#kgateway +[38]:#google-cloud-service-mesh +[39]:#kubvernor + + +[gamma]:mesh/index.md + + + +## 구현체 + +이 섹션에서는 특정 구현체들에 대한 블로그 게시글, 문서 및 기타 게이트웨이 API 참조에 대한 구체적인 링크를 찾을 수 있다. + +### Acnodal EPIC +[EPIC][epicdocs]는 쿠버네티스와 함께 설계되고 구축된 오픈 소스 외부 게이트웨이 플랫폼이다. 게이트웨이 클러스터, k8s 게이트웨이 컨트롤러, 독립형 리눅스 게이트웨이 컨트롤러 및 게이트웨이 서비스 매니저로 구성된다. 이들은 함께 클러스터 사용자에게 게이트웨이 서비스를 제공하는 플랫폼을 만든다. 각 게이트웨이는 워크로드 클러스터가 아닌 게이트웨이 클러스터에서 실행되는 여러 Envoy 인스턴스로 구성된다. 게이트웨이 서비스 매니저는 공용 및 사설 클러스터를 위한 Gateway-as-a-Service 인프라를 구현하고 비-k8s 엔드포인트를 통합하는 데 사용할 수 있는 간단한 사용자 관리 및 UI이다. + +- [문서][epicdocs] +- [소스 저장소][epicsource] + +[epicdocs]:https://www.epic-gateway.org/ +[epicsource]:https://github.com/epic-gateway + +### Airlock Microgateway +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.3.0-Airlock%20Microgateway-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.3.0/airlock-microgateway) + +[Airlock Microgateway][airlock-microgateway]는 쿠버네티스 환경에 최적화되고 RedHat OpenShift 인증을 받은 쿠버네티스 네이티브 WAAP(Web Application and API Protection, 이전 WAF) 솔루션이다. +현대적인 애플리케이션 보안이 개발 워크플로에 내장되어 DevSecOps 패러다임을 따른다. +Airlock Microgateway는 검증된 Airlock 보안 기능으로 애플리케이션과 마이크로서비스를 공격으로부터 보호하며, 높은 확장성도 제공한다. + +#### 기능 +- 알려진 공격(OWASP Top 10)으로부터 보호하는 거부 규칙, 헤더 필터링, JSON 파싱, OpenAPI 명세 강제 적용, GraphQL 스키마 검증과 같은 보안 기능을 갖춘 포괄적인 WAAP(이전 WAF) +- JWT 인증 또는 OIDC를 사용한 인증 강제를 가능하게 하는 ID 인식 프록시 +- 요청 라우팅 규칙, TLS 종료 및 원격 IP 추출을 포함한 리버스 프록시 기능 +- 허용 및 차단된 트래픽과 기타 메트릭에 대한 유용한 인사이트를 제공하는 사용하기 쉬운 Grafana 대시보드 + +#### 문서 및 링크 +- [제품 문서][airlock-microgateway-documentation] +- [게이트웨이 상세 문서][airlock-microgateway-guide] +- 도움을 위해 [Airlock 커뮤니티 포럼][airlock-microgateway-community-support]과 [지원 프로세스][airlock-microgateway-premium-support]를 확인하자. + +[airlock-microgateway]:https://www.airlock.com/en/secure-access-hub/components/microgateway +[airlock-microgateway-documentation]:https://docs.airlock.com/microgateway/latest +[airlock-microgateway-guide]:https://docs.airlock.com/microgateway/latest/?topic=MGW-00000142 +[airlock-microgateway-community-support]:https://forum.airlock.com/ +[airlock-microgateway-premium-support]:https://techzone.ergon.ch/support-process + +### Amazon Elastic Kubernetes Service + +[Amazon Elastic Kubernetes Service (EKS)][eks]는 자체 쿠버네티스 컨트롤 플레인이나 노드를 설치, 운영, 유지 관리할 필요 없이 AWS에서 쿠버네티스를 실행하는 데 사용할 수 있는 관리형 서비스이다. EKS는 [AWS 게이트웨이 API 컨트롤러][eks-gateway]를 통해 게이트웨이 API를 구현하며, 이 컨트롤러는 EKS 클러스터 내 게이트웨이 및 HTTPRoute를 위해 [Amazon VPC Lattice][vpc-lattice] 리소스를 프로비저닝한다. + +[eks]:https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html +[eks-gateway]:https://github.com/aws/aws-application-networking-k8s +[vpc-lattice]:https://aws.amazon.com/vpc/lattice/ + +### APISIX + +[Apache APISIX][apisix]는 동적이고 실시간이며 고성능인 API 게이트웨이이다. APISIX는 로드 밸런싱, 동적 업스트림, 카나리 릴리스, 서킷 브레이킹, 인증, 관찰 가능성 등과 같은 풍부한 트래픽 관리 기능을 제공한다. + +APISIX는 현재 [Apache APISIX 인그레스 컨트롤러][apisix-1]에 대해 게이트웨이 API `v1beta1` 버전의 명세를 지원한다. + +[apisix]:https://apisix.apache.org/ +[apisix-1]:https://github.com/apache/apisix-ingress-controller + +### Avi Kubernetes Operator + +[Avi Kubernetes Operator (AKO)][ako]는 VMware AVI Advanced Load Balancer를 사용하여 L4-L7 로드 밸런싱을 제공한다. + +AKO 버전 [v1.13.1]부터 게이트웨이 API 버전 v1.0.0이 지원된다. 게이트웨이 클래스, 게이트웨이 및 HTTPRoute 객체를 지원하는 게이트웨이 API 명세의 v1 버전을 구현한다. + +AKO 게이트웨이 API를 배포하고 사용하는 문서는 [Avi 쿠버네티스 오퍼레이터 게이트웨이 API][ako-gw]에서 찾을 수 있다. + +[ako]:https://techdocs.broadcom.com/us/en/vmware-security-load-balancing/avi-load-balancer/avi-kubernetes-operator/AKO/avi-kubernetes-operator-1-13/avi-kubernetes-operator.html +[ako-gw]:https://techdocs.broadcom.com/us/en/vmware-security-load-balancing/avi-load-balancer/avi-kubernetes-operator/AKO/avi-kubernetes-operator-1-13/gateway-api/gateway-api-v1.html +[v1.13.1]:https://github.com/vmware/load-balancer-and-ingress-services-for-kubernetes + +### Azure Application Gateway for Containers + +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Partial%20Conformance%20v1.1.1-Azure%20Application%20Gateway%20for%20Containers-orange)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.1.0/azure-application-gateway-for-containers) + +[Application Gateway for Containers][azure-application-gateway-for-containers]는 Azure의 쿠버네티스 클러스터에서 실행되는 워크로드에 대한 동적 트래픽 관리 기능을 제공하는 관리형 애플리케이션(레이어 7) 로드 밸런싱 솔루션이다. ALB 컨트롤러를 배포하고 게이트웨이 API를 시작하려면 [빠른 시작 가이드][azure-application-gateway-for-containers-quickstart-controller]를 따른다. + + +[azure-application-gateway-for-containers]:https://aka.ms/appgwcontainers/docs +[azure-application-gateway-for-containers-quickstart-controller]:https://learn.microsoft.com/azure/application-gateway/for-containers/quickstart-deploy-application-gateway-for-containers-alb-controller + +### Cilium + +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.0.0-Cilium-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.0.0/cilium) + +[Cilium][cilium]은 쿠버네티스 및 기타 네트워킹 환경을 위한 eBPF 기반 네트워킹, 관찰 가능성 및 보안 솔루션이다. +여기에는 [Cilium Service Mesh][cilium-service-mesh]가 포함되어 있으며, +이는 높은 효율을 가진 메시 데이터 플레인으로 [사이드카 없는 모드][cilium-sidecarless]에서 실행될 수 있어 성능을 크게 향상시키고, +사이드카로 인한 운영 복잡성을 피할 수 있다. +Cilium은 또한 사이드카 프록시 모델도 지원하여 사용자에게 선택권을 제공한다. +[Cilium 1.14][cilium114blog]부터 Cilium은 게이트웨이 API를 지원하며 v0.7.1에 대한 호환성을 +통과한다. + +Cilium은 오픈 소스이며 CNCF 졸업 프로젝트이다. + +Cilium 서비스 메시에 대한 질문이 있다면 [Cilium Slack][cilium-slack]의 #service-mesh 채널에서 시작하는 것이 좋다. +개발 노력에 기여하려면 #development 채널을 확인하거나, +[주간 개발자 회의][cilium-meeting]에 참여하자. + +[cilium]:https://cilium.io +[cilium-service-mesh]:https://docs.cilium.io/en/stable/gettingstarted/#service-mesh +[cilium-sidecarless]:https://isovalent.com/blog/post/cilium-service-mesh/ +[cilium114blog]:https://isovalent.com/blog/post/cilium-release-114/ +[cilium-slack]:https://cilium.io/slack +[cilium-meeting]:https://github.com/cilium/cilium#weekly-developer-meeting + +### Contour + +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.2.1-Contour-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.2.1/projectcontour-contour) + +[Contour][contour]는 쿠버네티스를 위한 CNCF 오픈 소스로 Envoy 기반 인그레스 컨트롤러이다. + +Contour [v1.31.0][contour-release]은 게이트웨이 API v1.2.1을 구현한다. +모든 [표준 채널][contour-standard] v1 API 그룹 리소스(게이트웨이 클래스, 게이트웨이, HTTPRoute, 레퍼런스그랜트)와 대부분의 v1alpha2 API 그룹 리소스(TLSRoute, TCPRoute, GRPCRoute, 레퍼런스그랜트, BackendTLSPolicy)가 지원된다. +Contour의 구현은 v1.2.1 릴리스에 포함된 대부분의 코어 확장 게이트웨이 API 호환성 테스트를 통과한다. + +Contour의 게이트웨이 API 구현을 배포하고 사용하는 방법에 대한 정보는 [Contour Gateway API Guide][contour-guide]를 확인하자. + +Contour의 구현에 대한 도움과 지원을 받으려면, [이슈를 생성][contour-issue-new]하거나 [쿠버네티스 slack의 #contour 채널][contour-slack]에서 도움을 요청하자. + +[contour]:https://projectcontour.io +[contour-release]:https://github.com/projectcontour/contour/releases/tag/v1.30.0 +[contour-standard]:concepts/versioning.md#release-channels +[contour-guide]:https://projectcontour.io/docs/1.30/guides/gateway-api/ +[contour-issue-new]:https://github.com/projectcontour/contour/issues/new/choose +[contour-slack]:https://kubernetes.slack.com/archives/C8XRH2R4J + +### Easegress + +[Easegress][easegress]는 클라우드 네이티브 트래픽 오케스트레이션 시스템이다. + +이 시스템은 현대적인 고급 게이트웨이, 견고한 분산 클러스터, 유연한 트래픽 오케스트레이터, 또는 접근 가능한 서비스 메시로 기능할 수 있다. + +Easegress는 현재 [게이트웨이 컨트롤러][easegress-gatewaycontroller]를 통해 게이트웨이 API `v1beta1` 버전의 명세를 지원한다. + +[easegress]:https://megaease.com/easegress/ +[easegress-gatewaycontroller]:https://github.com/megaease/easegress/blob/main/docs/04.Cloud-Native/4.2.Gateway-API.md + +### Emissary-Ingress (Ambassador API Gateway) + +[Emissary-Ingress][emissary] (이전 Ambassador API Gateway)는 [Envoy Proxy][envoy] 위에 구축된 +쿠버네티스용 인그레스 컨트롤러와 API 게이트웨이를 제공하는 오픈 소스 CNCF 프로젝트이다. +Emissary와 함께 게이트웨이 API를 사용하는 자세한 내용은 [여기][emissary-gateway-api]를 참조하자. + +[emissary]:https://www.getambassador.io/docs/edge-stack +[envoy]:https://envoyproxy.io +[emissary-gateway-api]:https://www.getambassador.io/docs/edge-stack/latest/topics/using/gateway-api/ + +### Envoy Gateway + +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.0.0-EnvoyGateway-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.0.0/envoy-gateway) + +[Envoy Gateway][eg-home]는 Envoy 기반 애플리케이션 게이트웨이를 관리하기 위한 [Envoy][envoy-org] 하위 프로젝트이다. +지원되는 게이트웨이 API의 API와 필드는 [여기][eg-supported]에 설명되어 있다. +몇 가지 간단한 단계로 게이트웨이 API와 함께 Envoy Gateway를 실행하려면 [빠른 시작][eg-quickstart]을 +사용하자. + +[eg-home]:https://gateway.envoyproxy.io/ +[envoy-org]:https://github.com/envoyproxy +[eg-supported]:https://gateway.envoyproxy.io/docs/tasks/quickstart/ +[eg-quickstart]:https://gateway.envoyproxy.io/docs/tasks/quickstart + +### Flomesh Service Mesh (FSM) + +[Flomesh Service Mesh][fsm]는 쿠버네티스 동/서 및 북/남 트래픽 관리를 위한 커뮤니티 주도의 경량 서비스 메시이다. Flomesh는 레이어4 트래픽 관리를 위해 [ebpf](https://www.kernel.org/doc/html/latest/bpf/index.html)를, 레이어7 트래픽 관리에 [pipy](https://flomesh.io/pipy) 프록시를 사용한다. Flomesh는 로드 밸런서, 크로스 클러스터 서비스 등록/발견을 내장으로 제공하며, 멀티 클러스터 네트워킹을 지원한다. `Ingress`("인그레스 컨트롤러"로서)와 게이트웨이 API를 지원한다. + +FSM의 게이트웨이 API 지원은 [Flomesh 게이트웨이 API][fgw] 위에 구축되며 현재 쿠버네티스 게이트웨이 API 버전 [v0.7.1](https://github.com/kubernetes-sigs/gateway-api/releases/tag/v0.7.1)을 지원하고 `v0.8.0` 지원이 현재 진행 중이다. + +- [FSM 쿠버네티스 게이트웨이 API 호환성 매트릭스](https://github.com/flomesh-io/fsm/blob/main/docs/gateway-api-compatibility.md) +- [FSM에서 게이트웨이 API 지원을 사용하는 방법](https://github.com/flomesh-io/fsm/blob/main/docs/tests/gateway-api/README.md) + +[fsm]:https://github.com/flomesh-io/fsm +[flomesh]:https://flomesh.io +[fgw]:https://github.com/flomesh-io/fgw + +### Gloo Gateway + +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.0.0-GlooGateway-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.0.0/gloo-gateway) +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Partial%20Conformance%20v1.1.0-GlooGateway-orange)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.1.0/gloo-gateway) + +[Solo.io][solo]의 [Gloo 게이트웨이][gloogateway]는 기능이 풍부한 쿠버네티스 네이티브 인그레스 컨트롤러이자 차세대 API 게이트웨이이다. +Gloo 게이트웨이는 기존 컨트롤 플레인 구현에 게이트웨이 API의 완전한 기능과 커뮤니티 지원을 제공한다. + +Gloo 게이트웨이 인그레스 컨트롤러는 `HTTPRouteServiceTypes`를 제외하고 +v1.1.0 릴리스의 GATEWAY_HTTP 호환성 프로필에 대한 모든 코어 게이트웨이 API 호환성 테스트를 통과한다. + +[gloogateway]:https://docs.solo.io/gateway/latest/ +[solo]:https://www.solo.io + +### Google Cloud Service Mesh + + +[Google Kubernetes Engine (GKE)][gke]는 구글 클라우드에서 제공하는 +관리형 쿠버네티스 플랫폼이다. + +GKE의 메시를 위한 게이트웨이 (GAMMA) 구현은 [클라우드 서비스 메시][cloud-service-mesh]를 통해 이루어진다. + + +구글 클라우드 서비스 메시는 [Envoy 기반 사이드카 메시][envoy-sidecar-mesh]와 [Proxyless-GRPC][proxyless-grpc-mesh] (GRPCRoute 사용)를 지원한다. + + +[gke]:https://cloud.google.com/kubernetes-engine +[cloud-service-mesh]:https://cloud.google.com/products/service-mesh +[envoy-sidecar-mesh]:https://cloud.google.com/service-mesh/docs/gateway/set-up-envoy-mesh +[proxyless-grpc-mesh]:https://cloud.google.com/service-mesh/docs/gateway/proxyless-grpc-mesh + +### Google Kubernetes Engine + +[![Conformance](https://img.shields.io/badge/Gateway_API_Partial_Conformance_v1.1.0-Google_Kubernetes_Engine-orange)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.1.0/gke-gateway) + +[Google 쿠버네티스 엔진 (GKE)][gke]은 구글 클라우드에서 제공하는 +관리형 쿠버네티스 플랫폼이다. +GKE의 게이트웨이 API 구현은 GKE 클러스터의 파드를 위한 구글 클라우드 로드 밸런서를 프로비저닝하는 +[GKE 게이트웨이 컨트롤러][gke-gateway]를 통해 이루어진다. + +GKE 게이트웨이 컨트롤러는 가중치 트래픽 분할, 미러링, 고급 라우팅, 멀티 클러스터 로드 밸런싱 등을 +지원한다. +[사설 또는 공용 게이트웨이][gke-gateway-deploy] 및 [멀티 클러스터 게이트웨이][gke-multi-cluster-gateway]를 +배포하는 방법은 문서를 참조한다. + +GKE 게이트웨이 컨트롤러는 `HTTPRouteHostnameIntersection`을 제외하고 +v1.1.0 릴리스의 GATEWAY_HTTP 호환성 프로필에 대한 모든 코어 게이트웨이 API 호환성 테스트를 통과한다. + +[gke]:https://cloud.google.com/kubernetes-engine +[gke-gateway]:https://cloud.google.com/kubernetes-engine/docs/concepts/gateway-api +[gke-gateway-deploy]:https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-gateways +[gke-multi-cluster-gateway]:https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-multi-cluster-gateways + +### HAProxy Ingress + +[HAProxy 인그레스][h1]는 HAProxy를 위한 커뮤니티 주도 인그레스 컨트롤러 구현이다. + +HAProxy 인그레스 v0.13은 게이트웨이 API의 v1alpha1 명세를 부분적으로 지원한다. 호환성과 로드맵에 대한 정보는 [컨트롤러의 게이트웨이 API 문서][h2]를 참조한다. + +[h1]:https://haproxy-ingress.github.io/ +[h2]:https://haproxy-ingress.github.io/docs/configuration/gateway-api/ + +### HAProxy Kubernetes Ingress Controller + +HAProxy 쿠버네티스 인그레스 컨트롤러는 HAProxy Technologies에서 유지 관리하는 오픈 소스 프로젝트로, 쿠버네티스를 위한 빠르고 효율적인 트래픽 관리, 라우팅 및 관찰 가능성을 제공한다. 버전 1.10부터 게이트웨이 API에 대한 내장 지원을 제공한다. 동일한 인그레스 컨트롤러 배포로 인그레스 API와 게이트웨이 API를 모두 사용할 수 있다. 자세한 내용은 [문서][haproxytech-docs-gw]를 참조하자. [GitHub 저장소][haproxytech-github-gw]에서 지원되는 API 리소스에 대한 추가 정보도 찾을 수 있다. + +[haproxytech-docs-gw]:https://www.haproxy.com/documentation/kubernetes-ingress/gateway-api/enable-gateway-api/ +[haproxytech-github-gw]:https://github.com/haproxytech/kubernetes-ingress/blob/master/documentation/gateway-api.md + +### HashiCorp Consul + +[HashiCorp][hashicorp]의 [Consul][consul]은 멀티 클라우드 네트워킹을 위한 오픈 소스 컨트롤 플레인이다. 단일 Consul 배포로 베어 메탈, VM 및 컨테이너 환경에 걸쳐 확장될 수 있다. + +Consul 서비스 메시는 모든 쿠버네티스 배포판에서 작동하고, 다중 클러스터를 연결을 지원하며, Consul CRD는 메시에서 트래픽 패턴과 권한을 관리하는 쿠버네티스 네이티브 워크플로를 제공한다. [Consul API 게이트웨이][consul-api-gw-docs]는 북/남 트래픽 관리를 위한 게이트웨이 API를 지원한다. + +게이트웨이 API의 지원되는 버전과 기능에 대한 최신 정보는 [Consul API 게이트웨이 문서][consul-api-gw-docs]를 확인하길 바란다. + +[consul]:https://consul.io +[consul-api-gw-docs]:https://www.consul.io/docs/api-gateway +[hashicorp]:https://www.hashicorp.com + +### Istio + +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.2.1-Istio-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.2.1/istio-istio) + +[Istio][istio]는 오픈 소스 [서비스 메시][istio-mesh] 및 게이트웨이 구현체이다. + +Istio의 최소 설치만으로 클러스터 인그레스 트래픽 제어를 위한 +쿠버네티스 게이트웨이 API 완전한 적합 구현을 사용할 수 있다. +서비스 메시 사용자를 위해, +Istio는 메시 내에서 [GAMMA 이니셔티브의][gamma] 게이트웨이 API +[동/서 트래픽 관리 지원][gamma]도 완전히 지원한다. + +모든 [인그레스 작업][istio-1]과 여러 메시 내부 트래픽 관리 작업을 포함한 Istio 문서의 대부분은 이미 게이트웨이 API 또는 Istio 구성 API를 사용하여 트래픽을 구성하는 병렬 지침을 포함한다. +게이트웨이 API 또는 Istio 구성 API를 사용하여 트래픽을 구성한다. +Istio의 게이트웨이 API 구현에 대한 자세한 정보는 [게이트웨이 API task][istio-2]를 확인하자. + +[istio]:https://istio.io +[istio-mesh]:https://istio.io/latest/docs/concepts/what-is-istio/#what-is-a-service-mesh +[istio-1]:https://istio.io/latest/docs/tasks/traffic-management/ingress/ +[istio-2]:https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/ + +### kgateway +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.2.1-kgateway-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.2.1/kgateway) + +[kgateway] 프로젝트는 기능이 풍부한 쿠버네티스 네이티브 인그레스 컨트롤러이자 차세대 API 게이트웨이이다. +우수한 HTTP 경험을 유지하는 데 중점을 두고 있으며, AI 및 MCP 게이트웨이와 같은 시나리오에서 고급 라우팅 기능을 확장하고, Istio와 같은 서비스 메쉬와 엠비언트 모드 및 사이드카 모드에서 상호 운용성을 지원한다. +이러한 초점은 많은 북/남 및 동/서 사용 사례에서 성능 효율적 방식인 합리적으로 분산된 Envoy 인스턴스 세트를 쉽게 구성할 수 있음을 의미한다. + +Kgateway는 2.0 릴리스와 함께 일반적으로 사용 가능하다. + +[kgateway]:https://kgateway.dev/docs + + +### Kong Kubernetes Ingress Controller + +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.2.1-Kong%20Ingress%20Controller-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.2.1/kong-kubernetes-ingress-controller) + +[Kong][kong]은 하이브리드 및 멀티 클라우드 환경을 위해 구축된 오픈 소스 API 게이트웨이이다. + +[Kong 쿠버네티스 인그레스 게이트웨이 (KIC)][kic]는 비관리형 게이트웨이를 구성하는 데 사용할 수 있다. 사용 정보는 [Gateway API Guide][kong-gw-guide]를 확인하자. + +Kong 쿠버네티스 인그레스 컨트롤러에 대한 도움과 지원을 받으려면 [이슈를 생성][kic-issue-new]하거나 [토론][kic-disc-new]을 만들자. [쿠버네티스 slack의 #kong 채널][kong-slack]에서도 도움을 요청할 수 있다. + +[kong]:https://konghq.com +[kic]:https://github.com/kong/kubernetes-ingress-controller +[kong-gw-guide]:https://docs.konghq.com/kubernetes-ingress-controller/latest/guides/using-gateway-api/ +[kic-issue-new]:https://github.com/Kong/kubernetes-ingress-controller/issues/new +[kic-disc-new]:https://github.com/Kong/kubernetes-ingress-controller/discussions/new +[kong-slack]:https://kubernetes.slack.com/archives/CDCA87FRD + +### Kong Gateway Operator + +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.2.0-Kong%20Gateway%20Operator-orange)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.2.0/kong-gateway-operator) + +[Kong][kong]은 하이브리드 및 멀티 클라우드 환경을 위해 구축된 오픈 소스 API 게이트웨이이다. + +[Kong 게이트웨이 오퍼레이터 (KGO)][kgo]는 관리형 게이트웨이를 구성하고, [Kong 쿠버네티스 인그레스 컨트롤러](#kong-kubernetes-ingress-controller)의 인스턴스를 오케스트레이션하는 데 사용할 수 있다. + +Kong 쿠버네티스 인그레스 컨트롤러에 대한 도움과 지원을 받으려면 [이슈를 생성][kgo-issue-new]하거나 [토론][kgo-disc-new]을 만들자. [쿠버네티스 slack의 #kong 채널][kong-slack]에서도 도움을 요청할 수 있다. + +[kgo]:https://docs.konghq.com/gateway-operator/latest/ +[kgo-issue-new]:https://github.com/Kong/gateway-operator/issues/new +[kgo-disc-new]:https://github.com/Kong/gateway-operator/discussions/new + + +### Kubvernor +[Kubvernor][kubvernor]는 Rust 프로그래밍 언어로 구현된 오픈소스이자 고도로 실험적인 API 컨트롤러이다. 현재 Kubvernor는 Envoy Proxy를 지원하며, 다양한 게이트웨이(Envoy, Nginx, HAProxy 등)를 관리/배포할 수 있도록 가능한 한 일반적인 구조를 목표로 한다. + +[kubvernor]:https://github.com/kubvernor/kubvernor + +### Kuma + +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.0.0-Kuma-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.0.0/kumahq-kuma) + +[Kuma][kuma]는 오픈 소스 서비스 메시이다. + +Kuma는 베타 안정성을 보장하며 Kuma 내장형, Envoy 기반 게이트웨이에 대한 게이트웨이 API 명세를 구현한다. 게이트웨이 API를 사용하여 Kuma 내장 게이트웨이를 설정하는 방법에 대한 정보는 [게이트웨이 API 문서][kuma-1]을 확인한다. + +Kuma 2.3 이상은 메시 내에서 [GAMMA 이니셔티브의][gamma] +게이트웨이 API [동/서 트래픽 관리 지원][gamma]을 지원한다. + +[kuma]:https://kuma.io +[kuma-1]:https://kuma.io/docs/latest/using-mesh/managing-ingress-traffic/gateway-api/ + +### Linkerd + +[Linkerd][linkerd]는 최초의 CNCF 졸업 [서비스 메시][linkerd-mesh]이다. +Envoy를 기반으로 하지 않은 유일한 주요 메쉬로, +대신 Rust로 특별히 설계된 마이크로 프록시를 활용해 +Kubernetes에 보안, 가시성, 신뢰성을 제공하며 복잡성을 제거한다. + +Linkerd 2.14 이상은 메시 내에서 [GAMMA 이니셔티브의][gamma] +게이트웨이 API [동/서 트래픽 관리 지원][gamma]을 지원한다. + +[linkerd]:https://linkerd.io/ +[linkerd-mesh]:https://buoyant.io/service-mesh-manifesto + +### LiteSpeed Ingress Controller + +[LiteSpeed 인그레스 컨트롤러](https://litespeedtech.com/products/litespeed-web-adc/features/litespeed-ingress-controller)는 LiteSpeed WebADC 컨트롤러를 사용하여 인그레스 컨트롤러 및 로드 밸런서로 동작하며, 쿠버네티스 클러스터 내의 트래픽을 관리한다. 이 컨틀로러는 게이트웨이, 게이트웨이 클래스, HTTPRoute, 레퍼런스그랜트를 포함한 게이트웨이 API의 코어 기능 전체와 cert-manager의 게이트웨이 기능을 구현하고 있다. 게이트웨이는 LiteSpeed Ingress Controller에 완전히 통합되어 있다. + +- [제품 문서](https://docs.litespeedtech.com/cloud/kubernetes/). +- [게이트웨이 상세 문서](https://docs.litespeedtech.com/cloud/kubernetes/gateway). +- 전체 지원은 [LiteSpeed support 웹사이트](https://www.litespeedtech.com/support)에서 제공한다. + +### LoxiLB + +[kube-loxilb][kube-loxilb-gh]는 [LoxiLB's][loxilb-org]가 구현한 게이트웨이 API 및 쿠버네티스 서비스 로드 밸런서 명세 구현체로, 로드 밸런서 클래스, 고급 IPAM(공유 또는 전용) 등을 지원한다. kube-loxilb는 L4 서비스 로드 밸런서로서 [LoxiLB][loxilb-gh]를 인그레스(L7) 리소스를 위해 [loxilb-ingress][loxilb-ingress-gh]를 사용하여 게이트웨이 API 리소스를 관리한다. + +간단한 단계로 게이트웨이 API와 함께 LoxiLB를 실행하려면 [빠른 시작 가이드][loxigw-guide]를 참고하자. + +[loxilb-home]:https://loxilb.io/ +[loxilb-org]:https://github.com/loxilb-io +[loxilb-gh]:https://github.com/loxilb-io/loxilb +[kube-loxilb-gh]:https://github.com/loxilb-io/kube-loxilb +[loxilb-ingress-gh]:https://github.com/loxilb-io/loxilb-ingress +[loxigw-guide]:https://docs.loxilb.io/latest/gw-api/ + +### NGINX Gateway Fabric + +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.2.1-NGINX Gateway Fabric-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.2.1/nginx-nginx-gateway-fabric) + +[NGINX 게이트웨이 패브릭][nginx-gateway-fabric]은 [NGINX][nginx]를 데이터 플레인으로 사용하는 게이트웨이 API의 구현체를 제공하는 오픈소스 프로젝트이다. 이 프로젝트의 목표는 쿠버네티스에서 실행되는 애플리케이션을 위한 HTTP 또는 TCP/UDP 로드 밸런서, 리버스 프록시 또는 API 게이트웨이를 구성하기 위해 코어 게이트웨이 API를 구현하는 것이다. [NGINX 문서][nginx-docs] 웹사이트에서 종합적인 NGINX 게이트웨이 패브릭 사용자 문서를 찾을 수 있다. + +지원되는 게이트웨이 API 리소스 및 기능 목록은 [게이트웨이 API 호환성][nginx-compat] 문서를 확인하자. + +NGINX 게이트웨이 패브릭에 대한 제안이 있거나 문제를 경험했다면 GitHub에서 [이슈를 생성][nginx-issue-new]하거나 [토론][nginx-disc-new]을 부탁한다. 또한 [NGINX 커뮤니티 포럼][nginx-forum]에서 도움도 요청할 수 있다. + +[nginx-gateway-fabric]:https://github.com/nginx/nginx-gateway-fabric +[nginx]:https://nginx.org/ +[nginx-docs]:https://docs.nginx.com/nginx-gateway-fabric/ +[nginx-compat]:https://docs.nginx.com/nginx-gateway-fabric/overview/gateway-api-compatibility/ +[nginx-issue-new]:https://github.com/nginx/nginx-gateway-fabric/issues/new +[nginx-disc-new]:https://github.com/nginx/nginx-gateway-fabric/discussions/new +[nginx-forum]:https://community.nginx.org/ + + +### ngrok Kubernetes Operator + +[ngrok 쿠버네티스 오퍼레이터][ngrok-k8s-operator]는 작년에 초기 지원을 추가한 이후로 게이트웨이 API의 전체 코어를 지원한다. 이것은 다음을 포함한다. + +- 라우트: (HTTPRoute, TCPRoute, TLSRoute) 및 RouteMatches (Header, Path, 등) +- 필터: Header, Redirect, Rewrite 등 +- 백엔드: 백엔드 Filters 및 가중치 기반 밸런싱 +- 레퍼런스그랜트: 멀티 테넌트 클러스터 처리를 위한 RBAC +- 게이트웨이 API가 충분히 유연하지 않은 경우, extensionRef 또는 어노테이션으로 트래픽 정책 설정 + +자세한 내용은[docs][ngrok-k8s-gwapi-docs]를 참고하자. 기능 요청이나 버그 리포트는 [create an issue][ngrok-issue-new]을 통해 제출을 부탁한다. 또한 [Slack][ngrok-slack]에서 도움을 받을 수 있다. + +[ngrok-k8s-operator]:https://github.com/ngrok/ngrok-operator +[ngrok]:https://ngrok.com +[ngrok-k8s-gwapi-docs]:https://ngrok.com/docs/k8s/ +[ngrok-issue-new]: https://github.com/ngrok/ngrok-operator/issues/new/choose +[ngrok-slack]:https://ngrokcommunity.slack.com/channels/general + +### STUNner + +[STUNner][stunner]는 쿠버네티스용 오픈소스 클라우드 네이티브 WebRTC 미디어 게이트웨이이다. STUNner는 WebRTC 미디어 스트림을 쿠버네티스 클러스터로 원활하게 수신하기 위한 목적으로 설계되었으며, 간소화된 NAT 트래버설과 동적 미디어 라우팅을 제공한다. 동시에 STUNner는 대규모 실시간 통신 서비스에 대해 보안성과 모니터링 기능을 향상시킨다. STUNner의 데이터 플레인은 WebRTC 클라이언트를 위한 표준 규격의 TURN 서비스를 제공하며, 컨트롤 플레인은 게이트웨이 API의 일부를 지원한다. + +현재 STUNner는 게이트웨이 API 명세의 `v1alpha2` 버전을 지원한다. WebRTC 미디어 수신을 위해 STUNner를 배포하고 사용하는 방법은 [설치 가이드][stunner-1]를 확인하자. STUNner와 관련된 모든 질문, 의견 및 버그 리포트는 [STUNner 프로젝트][stunner]로 보내주시기 바란다. + +[stunner]:https://github.com/l7mp/stunner +[stunner-1]:https://github.com/l7mp/stunner/blob/main/doc/INSTALL.md + +### Traefik Proxy + +[![Conformance](https://img.shields.io/badge/Gateway%20API%20Conformance%20v1.2.1-Traefik Proxy-green)](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/v1.2.1/traefik-traefik) + +[Traefik Proxy][traefik-proxy]는 오픈 소스 클라우드 네이티브 애플리케이션 프록시이다. + +Traefik 프록시는 현재 게이트웨이 API 명세의 `v1.2.1` 버전을 지원한다. 배포 및 사용 방법에 대한 자세한 정보는 [쿠버네티스 제공자 문서][traefik-proxy-gateway-api-doc]를 확인하자. +Traefik 프록시의 구현은 GRPCRoute와 같은 모든 HTTP 코어 및 일부 확장 호환성 테스트를 통과하며, 실험적 채널의 TCPRoute 및 TLSRoute 기능도 지원한다. + +Traefik 프록시에 대한 도움과 지원을 받으려면, [이슈를 생성][traefik-proxy-issue-new]하거나 [Traefik Labs 커뮤니티 포럼][traefiklabs-community-forum]에서 도움을 요청하자. + +[traefik-proxy]:https://traefik.io +[traefik-proxy-gateway-api-doc]:https://doc.traefik.io/traefik/v3.2/routing/providers/kubernetes-gateway/ +[traefik-proxy-issue-new]:https://github.com/traefik/traefik/issues/new/choose +[traefiklabs-community-forum]:https://community.traefik.io/c/traefik/traefik-v3/21 + +### Tyk + +[Tyk 게이트웨이][tyk-gateway]는 클라우드 네이티브 오픈소스 API 게이트웨이이다. + +[Tyk.io][tyk] 팀은 게이트웨이 API 구현을 목표로 작업 중이며, 이 프로젝트의 진행 상황은 [여기][tyk-operator]에서 확인할 수 있다. + +[tyk]:https://tyk.io +[tyk-gateway]:https://github.com/TykTechnologies/tyk +[tyk-operator]:https://github.com/TykTechnologies/tyk-operator + +### WSO2 APK + +[WSO2 APK][wso2-apk]는 쿠버네티스 환경을 위해 특별히 설계된 API 관리 솔루션으로, API 관리를 위한 통합성, 유연성, 확장성을 조직에 제공한다. + +WSO2 APK는 게이트웨이 API를 구현하며, 게이트웨이 및 HTTPRoute 기능을 포함한다. 또한, 사용자 정의 리소스(CR)를 통해 레이트 리밋팅, 인증/인가, 분석/관찰 가능성을 지원한다. + +게이트웨이 API의 지원 버전과 기능에 대한 최신 정보는 [APK 게이트웨이 문서][apk-doc]를 참고하자. 질문이 있거나 기여하고 싶다면 자유롭게 [이슈 또는 풀 리퀘스트][repo]를 생성할 수 있다. 또한 [Discord 채널][discord]에서 우리와 소통하고 토론에 참여할 수 있다. + +[wso2-apk]:https://apk.docs.wso2.com/en/latest/ +[apk-doc]:https://apk.docs.wso2.com/en/latest/catalogs/kubernetes-crds/ +[repo]:https://github.com/wso2/apk +[discord]:https://discord.com/channels/955510916064092180/1113056079501332541 + +## 통합 + +이 섹션에서는 특정 통합을 위한 블로그 포스트, 문서 및 기타 게이트웨이 API 참조에 대한 구체적인 링크를 찾을 수 있다. + +### Flagger + +[Flagger][flagger]는 쿠버네티스에서 실행되는 애플리케이션의 릴리스 프로세스를 자동화하는 점진적 배포 도구이다. + +Flagger는 게이트웨이 API를 사용하여 카나리 배포와 A/B 테스트를 자동화하는 데 사용할 수 있다. 게이트웨이 API의 `v1alpha2`와 `v1beta1` 명세를 모두 지원한다. 게이트웨이 API의 모든 구현과 함께 Flagger를 사용하려면 [이 튜토리얼][flagger-tutorial]을 참조한다. + +[flagger]:https://flagger.app +[flagger-tutorial]:https://docs.flagger.app/tutorials/gatewayapi-progressive-delivery + +### cert-manager + +[cert-manager][cert-manager]는 클라우드 네이티브 환경에서 인증서 관리를 자동화하기 위한 도구이다. + +cert-manager는 게이트웨이 리소스를 위한 TLS 인증서를 생성할 수 있다. 이는 게이트웨이에 어노테이션을 추가하여 구성된다. 현재 게이트웨이 API의 `v1alpha2` 명세를 지원한다. 사용해보려면 [cert-manager 문서][cert-manager-docs]를 참조한다. + +[cert-manager]:https://cert-manager.io/ +[cert-manager-docs]:https://cert-manager.io/docs/usage/gateway/ + +### Argo rollouts + +[Argo Rollouts][argo-rollouts]는 쿠버네티스를 위한 점진적 배포 컨트롤러이다. 블루/그린 및 카나리와 같은 여러 고급 배포 방법을 지원한다. Argo Rollouts는 [플러그인][argo-rollouts-plugin]을 통해 게이트웨이 API를 지원한다. + +[argo-rollouts]:https://argo-rollouts.readthedocs.io/en/stable/ +[argo-rollouts-plugin]:https://github.com/argoproj-labs/rollouts-gatewayapi-trafficrouter-plugin/ + +### Knative + +[Knative][knative]는 쿠버네티스 위에 구축된 서버리스 플랫폼이다. Knative Serving은 URL의 자동 관리, 리비전 간 트래픽 분할, 요청 기반 자동 스케일링(제로 스케일 포함), 자동 TLS 프로비저닝과 함께 상태 비저장 컨테이너를 실행하기 위한 간단한 API를 제공한다. Knative Serving은 플러그인 아키텍처를 통해 다중 HTTP 라우터를 지원하며, 이는 모든 Knative 기능이 지원되지 않아 현재 알파 단계에 있는 [게이트웨이 API 플러그인][knative-net-gateway-api]을 포함한다. + +[knative]:https://knative.dev/ +[knative-net-gateway-api]:https://github.com/knative-sandbox/net-gateway-api + +### Kuadrant + +[Kuadrant][kuadrant]는 다른 게이트웨이 API 제공자와 통합되고 정책 연결을 통해 정책을 제공하는 오픈 소스 멀티 클러스터 게이트웨이 API 컨트롤러이다. + +Kuadrant는 게이트웨이를 중앙에서 정의하고 모든 게이트웨이에 적용되는 DNS, TLS, 인증 및 레이트 리밋팅과 같은 정책을 연결하기 위한 게이트웨이 API를 지원한다. + +Kuadrant는 Istio와 Envoy Gateway를 기본 게이트웨이 API 제공자로 지원하며, 향후 다른 게이트웨이 제공자와도 작동할 계획이다. + +Kuadrant의 구현에 대한 도움과 지원을 받으려면, 자유롭게 [이슈를 생성][kuadrant-issue-new]하거나 [쿠버네티스 slack의 #kuadrant 채널][kuadrant-slack]에서 도움을 요청하자. + +[kuadrant]:https://kuadrant.io/ +[kuadrant-issue-new]:https://github.com/Kuadrant/kuadrant-operator/issues/new +[kuadrant-slack]:https://kubernetes.slack.com/archives/C05J0D0V525 + diff --git a/site-src/ko/implementations/v1.0.md b/site-src/ko/implementations/v1.0.md new file mode 100644 index 0000000000..d23695b075 --- /dev/null +++ b/site-src/ko/implementations/v1.0.md @@ -0,0 +1,48 @@ + +아래의 표는 [프로젝트 구현체에서 업로드한](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports) 호환성 보고서에서 채워진다. 각 프로젝트가 보고서에 나열한 지원하는 확장 기능에 따라 분리되어 있다. +구현체는 리소스 타입에 대한 코어 호환성을 통과한 경우에만 이 페이지에 나타나며, 나열된 기능들은 확장 기능이어야 한다. 테스트를 건너뛴 호환성 보고서를 제출한 구현체는 테이블에 나타나지 않는다. + + + +???+ warning + + + 이 페이지는 활발하게 개발 중이며 최종 형태가 아니다. + 특히 프로젝트 이름과 기능 이름들의 경우에 그러하다. + 하지만 제출된 호환성 보고서를 기반으로 하므로 정보는 정확하다. + + +## 게이트웨이 프로필 + +### HTTPRoute + +| Organization | Project | Version | HTTPRoute Method Matching | HTTPRoute Query Param Matching | HTTPRoute Response Header Modification | HTTPRoute Backend Timeout | HTTPRoute Port Redirect | HTTPRoute Path Redirect | HTTPRoute Host Rewrite | HTTPRoute Scheme Redirect | HTTPRoute Path Rewrite | HTTPRoute Parent Ref Port | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Timeout | +|:----------------|:-----------------------------------|:--------------|:----------------------------|:---------------------------------|:-----------------------------------------|:----------------------------|:--------------------------|:--------------------------|:-------------------------|:----------------------------|:-------------------------|:----------------------------|:---------------------------|:-------------------------------------|:----------------------------| +| Kong | kubernetes-ingress-controller | v3.0.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.1.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Microsoft Azure | Application Gateway for Containers | v1.0.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.15.0-pre.3 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v0.6.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kumahq | kuma | 2.6.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.1.0 | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.2.0 | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | +| projectcontour | contour | v1.28.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.28.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.28.3 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.28.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.28.5 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.28.6 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.29.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.29.1 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| projectcontour | contour | v1.29.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| solo.io | gloo-gateway | v1.17.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | + +## 메시 프로필 + +### HTTPRoute + +| Organization | Project | Version | HTTPRoute Request Timeout | HTTPRoute Path Redirect | HTTPRoute Request Mirror | HTTPRoute Path Rewrite | HTTPRoute Method Matching | HTTPRoute Request Multiple Mirrors | HTTPRoute Backend Timeout | HTTPRoute Response Header Modification | HTTPRoute Port Redirect | HTTPRoute Scheme Redirect | HTTPRoute Host Rewrite | HTTPRoute Query Param Matching | +|:---------------|:----------|:----------|:----------------------------|:--------------------------|:---------------------------|:-------------------------|:----------------------------|:-------------------------------------|:----------------------------|:-----------------------------------------|:--------------------------|:----------------------------|:-------------------------|:---------------------------------| +| istio | istio | 1.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kumahq | kuma | 2.6.0 | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | \ No newline at end of file diff --git a/site-src/ko/implementations/v1.1.md b/site-src/ko/implementations/v1.1.md new file mode 100644 index 0000000000..aa4cb9be09 --- /dev/null +++ b/site-src/ko/implementations/v1.1.md @@ -0,0 +1,70 @@ + +아래의 표는 [프로젝트 구현체에서 업로드한](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports) 호환성 보고서에서 채워진다. 각 프로젝트가 보고서에 나열한 지원하는 확장 기능에 따라 분리되어 있다. +구현체는 리소스 타입에 대한 코어 호환성을 통과한 경우에만 이 페이지에 나타나며, 나열된 기능들은 확장 기능이어야 한다. 테스트를 건너뛴 호환성 보고서를 제출한 구현체는 테이블에 나타나지 않는다. + + + +???+ warning + + + 이 페이지는 활발하게 개발 중이며 최종 형태가 아니다. + 특히 프로젝트 이름과 기능 이름들의 경우에 그러하다. + 하지만 제출된 호환성 보고서를 기반으로 하므로 정보는 정확하다. + + +## 게이트웨이 프로필 + +### HTTPRoute + +| Organization | Project | Version | Mode | Gateway Port 8080 | HTTPRoute Host Rewrite | HTTPRoute Path Redirect | HTTPRoute Request Mirror | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | HTTPRoute Method Matching | HTTPRoute Path Rewrite | HTTPRoute Query Param Matching | HTTPRoute Port Redirect | HTTPRoute Parent Ref Port | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Timeout | +|:----------------|:-----------------------------------|:-------------------|:---------------------------------|:--------------------|:-------------------------|:--------------------------|:---------------------------|:-----------------------------------------|:----------------------------|:----------------------------|:-------------------------|:---------------------------------|:--------------------------|:----------------------------|:----------------------------------|:---------------------------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:-------------------------------------|:----------------------------| +| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-global-external-managed | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-regional-external-managed | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| GKE | gke-gateway | 1.30.3-gke.1211000 | gke-l7-rilb | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.2.0 | expressions | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.3.1 | expressions | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Microsoft Azure | Application Gateway for Containers | 1.3.7 | default | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | v4.4.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.22 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v1.3.0 | default | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.4.0 | default | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| projectcontour | contour | v1.30.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| solo.io | gloo-gateway | v1.18.0-beta30 | default | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| traefik | traefik | v3.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | + +### GRPCRoute + +| Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Port 8080 | Gateway Static Addresses | +|:----------------|:-----------------------------------|:----------|:------------|:----------------------------------|:--------------------|:---------------------------| +| Kong | kubernetes-ingress-controller | v3.2.0 | expressions | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.3.1 | expressions | :x: | :x: | :x: | +| Microsoft Azure | Application Gateway for Containers | 1.3.7 | default | :x: | :x: | :x: | +| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.22 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v1.3.0 | default | :x: | :x: | :x: | +| nginx | nginx-gateway-fabric | v1.4.0 | default | :x: | :x: | :x: | +| projectcontour | contour | v1.30.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | + +### TLSRoute + +| Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:---------------------|:----------|:--------|:----------------------------------|:--------------------|:---------------------------| +| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | v1.1.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.22 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v1.4.0 | default | :x: | :x: | :x: | +| projectcontour | contour | v1.30.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | + +## 메시 프로필 + +### HTTPRoute + +| Organization | Project | Version | Mode | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Mesh Cluster IP Matching | Mesh Consumer Route | HTTPRoute Parent Ref Port | +|:---------------|:----------|:----------|:--------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:-------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:---------------------------|:----------------------|:----------------------------| +| cilium | cilium | v1.16.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| istio | istio | 1.22 | default | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | \ No newline at end of file diff --git a/site-src/ko/implementations/v1.2.md b/site-src/ko/implementations/v1.2.md new file mode 100644 index 0000000000..48bdf18430 --- /dev/null +++ b/site-src/ko/implementations/v1.2.md @@ -0,0 +1,64 @@ + +아래의 표는 [프로젝트 구현체에서 업로드한](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports) 호환성 보고서에서 채워진다. 각 프로젝트가 보고서에 나열한 지원하는 확장 기능에 따라 분리되어 있다. +구현체는 리소스 타입에 대한 코어 호환성을 통과한 경우에만 이 페이지에 나타나며, 나열된 기능들은 확장 기능이어야 한다. 테스트를 건너뛴 호환성 보고서를 제출한 구현체는 테이블에 나타나지 않는다. + + + +???+ warning + + + 이 페이지는 활발하게 개발 중이며 최종 형태가 아니다. + 특히 프로젝트 이름과 기능 이름들의 경우에 그러하다. + 하지만 제출된 호환성 보고서를 기반으로 하므로 정보는 정확하다. + + +## 게이트웨이 프로필 + +### HTTPRoute + +| Organization | Project | Version | Mode | HTTPRoute Host Rewrite | HTTPRoute Path Rewrite | HTTPRoute Response Header Modification | HTTPRoute Method Matching | HTTPRoute Query Param Matching | Gateway Infrastructure Propagation | Gateway Port 8080 | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Parent Ref Port | HTTPRoute Port Redirect | HTTPRoute Request Timeout | HTTPRoute Scheme Redirect | HTTPRoute Path Redirect | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Request Header Modification | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | +|:---------------|:------------------------------|:----------|:-----------------------|:-------------------------|:-------------------------|:-----------------------------------------|:----------------------------|:---------------------------------|:-------------------------------------|:--------------------|:---------------------------------|:----------------------------------------|:----------------------------|:--------------------------------------|:----------------------------|:--------------------------|:----------------------------|:----------------------------|:--------------------------|:----------------------------------|:---------------------------|:------------------------------------------------|:---------------------------|:-------------------------------------| +| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.5.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| kgateway-dev | kgateway | v2.0.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :x: | +| nginx | nginx-gateway-fabric | v1.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | +| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| traefik | traefik | v3.2.2 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | + +### GRPCRoute + +| Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:------------------------------|:----------|:-----------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| +| Kong | kubernetes-ingress-controller | v3.4.0 | traditional_compatible | :x: | :x: | :x: | :x: | +| Kong | kubernetes-ingress-controller | v3.4.0 | expressions | :x: | :x: | :x: | :x: | +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v1.6.0 | default | :x: | :x: | :x: | :x: | +| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| traefik | traefik | v3.2.2 | default | :x: | :x: | :x: | :x: | + +### TLSRoute + +| Organization | Project | Version | Mode | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:---------------------|:----------|:--------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| nginx | nginx-gateway-fabric | v1.6.0 | default | :x: | :x: | :x: | :x: | +| projectcontour | contour | v1.31.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| traefik | traefik | v3.2.2 | default | :x: | :x: | :x: | :x: | + +## 메시 프로필 + +### HTTPRoute + +| Organization | Project | Version | Mode | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Mesh Cluster IP Matching | HTTPRoute Parent Ref Port | Mesh Consumer Route | +|:---------------|:----------|:----------|:--------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:---------------------------|:----------------------------|:----------------------| +| cilium | cilium | v1.17 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | +| istio | istio | 1.24 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | \ No newline at end of file diff --git a/site-src/ko/implementations/v1.3.md b/site-src/ko/implementations/v1.3.md new file mode 100644 index 0000000000..14c72cb39e --- /dev/null +++ b/site-src/ko/implementations/v1.3.md @@ -0,0 +1,49 @@ + +아래의 표는 [프로젝트 구현체에서 업로드한](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports) 호환성 보고서에서 채워진다. 각 프로젝트가 보고서에 나열한 지원하는 확장 기능에 따라 분리되어 있다. +구현체는 리소스 타입에 대한 코어 호환성을 통과한 경우에만 이 페이지에 나타나며, 나열된 기능들은 확장 기능이어야 한다. 테스트를 건너뛴 호환성 보고서를 제출한 구현체는 테이블에 나타나지 않는다. + + + +???+ warning + + + 이 페이지는 활발하게 개발 중이며 최종 형태가 아니다. + 특히 프로젝트 이름과 기능 이름들의 경우에 그러하다. + 하지만 제출된 호환성 보고서를 기반으로 하므로 정보는 정확하다. + + +## 게이트웨이 프로필 + +### HTTPRoute + +| Organization | Project | Version | Mode | Gateway Infrastructure Propagation | Gateway Port 8080 | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Parent Ref Port | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Static Addresses | HTTPRoute Backend Request Header Modification | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | +|:---------------|:--------------|:----------|:--------|:-------------------------------------|:--------------------|:---------------------------------|:----------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:------------------------|:----------------------------------|:---------------------------|:------------------------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------| +| airlock | microgateway | 4.6.0 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :x: | +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | + +### GRPCRoute + +| Organization | Project | Version | Mode | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:--------------|:----------|:--------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | :x: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | + +### TLSRoute + +| Organization | Project | Version | Mode | Gateway Address Empty | Gateway HTTP Listener Isolation | Gateway Infrastructure Propagation | Gateway Port 8080 | Gateway Static Addresses | +|:---------------|:--------------|:----------|:--------|:------------------------|:----------------------------------|:-------------------------------------|:--------------------|:---------------------------| +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| envoyproxy | envoy-gateway | latest | default | :x: | :x: | :x: | :x: | :x: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | + +## 메시 프로필 + +### HTTPRoute + +| Organization | Project | Version | Mode | HTTPRoute Backend Protocol H2C | HTTPRoute Backend Protocol Web Socket | HTTPRoute Backend Request Header Modification | HTTPRoute Backend Timeout | HTTPRoute Destination Port Matching | HTTPRoute Host Rewrite | HTTPRoute Method Matching | HTTPRoute Path Redirect | HTTPRoute Path Rewrite | HTTPRoute Port Redirect | HTTPRoute Query Param Matching | HTTPRoute Request Mirror | HTTPRoute Request Multiple Mirrors | HTTPRoute Request Percentage Mirror | HTTPRoute Request Timeout | HTTPRoute Response Header Modification | HTTPRoute Scheme Redirect | Mesh Cluster IP Matching | HTTPRoute Parent Ref Port | Mesh Consumer Route | +|:---------------|:----------|:----------|:--------|:---------------------------------|:----------------------------------------|:------------------------------------------------|:----------------------------|:--------------------------------------|:-------------------------|:----------------------------|:--------------------------|:-------------------------|:--------------------------|:---------------------------------|:---------------------------|:-------------------------------------|:--------------------------------------|:----------------------------|:-----------------------------------------|:----------------------------|:---------------------------|:----------------------------|:----------------------| +| cilium | cilium | main | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | +| istio | istio | 1.26.1 | default | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | \ No newline at end of file diff --git a/site-src/ko/index.md b/site-src/ko/index.md new file mode 100644 index 0000000000..17de530e83 --- /dev/null +++ b/site-src/ko/index.md @@ -0,0 +1,211 @@ +# 소개 + +게이트웨이 API는 +쿠버네티스의 L4 및 L7 라우팅에 초점을 맞춘 공식 쿠버네티스 프로젝트이다. +이 프로젝트는 쿠버네티스 인그레스, 로드 밸런싱, 서비스 메시 API의 차세대 버전을 대표한다. +시작부터 범용적이고 표현력이 풍부하며 역할 중심으로 설계되었다. + +전체 리소스 모델은 3개의 개별 +[페르소나](concepts/roles-and-personas.md)와 +그들이 관리할 것으로 예상되는 리소스에 초점을 맞춘다. + + +Gateway API Resource Model + +이 API의 대부분의 설정은 라우팅 레이어에 포함되어 있다. +이러한 프로토콜별 리소스 +([HTTPRoute](api-types/httproute.md), [GRPCRoute](api-types/grpcroute.md) 등)는 +인그레스와 메시 모두에 대해 고급 라우팅 기능을 제공한다. + +게이트웨이 API 로고는 API의 이중 목적을 시각적으로 설명하며, +북/남 (인그레스) 및 동/서 (메시) 트래픽이 +동일한 구성 설정을 공유하며 라우팅을 가능하게 한다. + +Gateway API Logo + +## 인그레스를 위한 게이트웨이 API + +??? success "v0.5.0 부터 표준 채널" + + 게이트웨이, 게이트웨이클래스, HTTPRoute는 v0.5.0부터 게이트웨이 + API의 표준 채널에 포함되었으며 안정적인 API로 간주된다. + 자세한 내용은 [버전 관리 가이드](concepts/versioning.md)를 참조하자. + +게이트웨이 API를 사용하여 인그레스 트래픽을 관리할 때, +[게이트웨이](api-types/gateway.md) 리소스는 트래픽이 +여러 컨텍스트를 거쳐 라우팅될 수 있는 접근 지점을 정의한다. +예를 들어, 클러스터 외부에서 내부로의 ([북/남 트래픽])이 있다. + +각 게이트웨이는 [게이트웨이클래스](api-types/gatewayclass.md)와 연결되며, +이는 게이트웨이의 트래픽을 처리할 [게이트웨이 컨트롤러]의 실제 타입을 설명한다. +개별 라우팅 리소스(예: [HTTPRoute](api-types/httproute.md))는 +[게이트웨이 리소스와 연결된다][게이트웨이 리소스 연결]. +이러한 서로 다른 관심사를 별도의 리소스로 분리하는 것은 +게이트웨이 API의 역할 지향적 특성의 핵심 부분이며, +동일한 클러스터 내에서 +여러 타입의 게이트웨이 컨트롤러(게이트웨이클래스 리소스로 표현)와 +각각의 여러 인스턴스(게이트웨이 리소스로 표현)를 허용한다. + +[인그레스 API]:https://kubernetes.io/ko/docs/concepts/services-networking/ingress/ +[북/남 트래픽]:concepts/glossary.md#northsouth-traffic +[동/서 트래픽]:concepts/glossary.md#eastwest-traffic +[게이트웨이 컨트롤러]:concepts/glossary.md#gateway-controller +[게이트웨이 리소스 연결]:concepts/api-overview.md#attaching-routes-to-gateways + +## 서비스 메시를 위한 게이트웨이 API ([GAMMA initiative](mesh/gamma.md)) + +??? success "v1.1.0 부터 표준 채널" + + 서비스 메시 사용 사례를 지원하기 위한 [GAMMA 이니셔티브](mesh/gamma.md) + 작업은 v1.1.0부터 표준 채널에 포함되었으며 GA로 간주된다. + 자세한 내용은 [버전 관리 가이드](concepts/versioning.md)를 참조하자. + +게이트웨이 API를 사용하여 [서비스 메시][서비스-메시]를 관리할 때는 상황이 약간 다르다. +클러스터 내에서 일반적으로 하나의 메시만 활성화되므로 +[게이트웨이](api-types/gateway.md)와 [게이트웨이클래스](api-types/gatewayclass.md) 리소스는 +사용되지 않는다. +대신, 개별 라우팅 리소스(예: [HTTPRoute](api-types/httproute.md))는 +[서비스 리소스와 직접 연결][메시-연결]되며, 이를 통해 메시가 해당 서비스로 향하는 +모든 트래픽을 관리하면서 +게이트웨이 API의 역할 지향적 특성을 유지한다. + +현재까지 [GAMMA](mesh/index.md)는 게이트웨이 API에 +최소한의 변경만으로 메시 기능을 지원해왔다. +하지만 GAMMA에서 특히 빠르게 중요해진 영역은 +[서비스 리소스의 다양한 측면][서비스-측면] 정의이다. + +[gamma]:mesh/index.md +[서비스-메시]:concepts/glossary.md#service-mesh +[서비스-측면]:mesh/service-facets.md +[메시-연결]:mesh/index.md + +## 시작하기 + +게이트웨이 API 사용에 관심 있는 사용자든, +API 준수를 원하는 구현자든, +아래의 리소스는 필요한 배경 정보를 제공한다. + +- [API 개요](concepts/api-overview.md) +- [사용자 가이드](guides/index.md) +- [구현](implementations.md) +- [API 참조 사양](reference/spec.md) +- [커뮤니티 링크](contributing/index.md)와 [개발자 가이드](contributing/devguide.md) + +## 게이트웨이 API 개념 +이어지는 설계 목표는 게이트웨이 API의 개념을 이끌어낸다. +이는 게이트웨이가 인그레스와 같은 현재 표준을 어떻게 개선하려는지 보여준다. + +- **역할-지향적** - 게이트웨이는 쿠버네티스 서비스 네트워킹을 사용하고 설정하는 조직적 역할을 +모델링하는 API 리소스로 구성되어 있다. +- **이식성** - 이는 개선이라기보다는 유지해야 할 특성이다. +인그레스가 +[수많은 구현](https://kubernetes.io/ko/docs/concepts/services-networking/ingress-controllers/)을 가진 보편적 사양인 것처럼, +게이트웨이 API는 다양한 구현을 지원하는 +이식 가능한 사양으로 설계되었다. +- **표현력** - 게이트웨이 API 리소스는 +헤더 기반 매칭, 트래픽 가중치 설정 등 +인그레스에서는 사용자 정의 주석을 통해서만 가능했던 핵심 기능을 지원한다. +- **확장 가능** - 게이트웨이 API는 API의 다양한 계층에서 +사용자 정의 리소스를 연결할 수 있도록 한다. +이를 통해 API 구조 내 적절한 위치에서 세분화된 사용자 정의가 가능하다. + +기타 주목할 만한 기능은 다음과 같다. + +- **게이트웨이클래스** - 게이트웨이클래스는 부하 분산 구현의 타입을 공식화한다. +이러한 클래스는 사용자가 쿠버네티스 리소스 모델을 통해 +어떤 기능이 사용 가능한지 +명확하고 쉽게 이해할 수 있도록 한다. +- **공유 게이트웨이와 네임스페이스 간 지원** - 독립적인 라우트 리소스가 +동일한 게이트웨이에 연결될 수 있도록 하여 로드 밸런서와 VIPs를 공유한다. +이를 통해 팀(심지어 네임스페이스를 넘어) 간 +직접적인 조정 없이 안전하게 인프라를 공유할 수 있다. +- **타입화된 라우트 및 백엔드** - 게이트웨이 API는 +타입화된 라우트 리소스와 다양한 백엔드 타입을 지원한다. +이를 통해 API는 (HTTP, gRPC와 같이) 다양한 프로토콜과 +(쿠버네티스 서비스, 스토리지 버킷, 함수와 같은) 다양한 백엔드 타겟을 +지원하는 데 유연성을 갖는다. +- 실험적 **서비스 메시 지원** ([GAMMA 이니셔티브][gamma]) - +게이트웨이 API는 라우팅 리소스를 서비스 리소스와 연결하여 +인그레스 컨트롤러뿐만 아니라 서비스 메시를 구성할 수 있도록 지원한다. + +## 왜 역할 지향적 API가 중요한가? + +도로, 전력, 데이터 센터, 쿠버네티스 클러스터 등 인프라는 공유를 목적으로 구축된다. +하지만 공유 인프라는 공통적인 도전 과제를 제시한다. +즉, 인프라 사용자에게 유연성을 제공하면서 +인프라 소유자의 통제력을 어떻게 유지할 것인가? + +게이트웨이 API는 쿠버네티스 서비스 네트워킹을 위한 역할 지향적 설계를 통해 +분산된 유연성과 중앙 집중식 통제 간의 균형을 이룬다. +이를 통해 공유 네트워크 인프라(하드웨어 부하 분산기, 클라우드 네트워킹, 클러스터 호스팅 프록시 등)를 +클러스터 운영자가 설정한 정책과 제약에 따라 +서로 협력하지 않는 다양한 팀이 사용할 수 +있다. + +게이트웨이 API의 설계에 사용되는 역할은 세 가지 페르소나로 정의된다. + +### 페르소나 + +- **Ian** (그/그의)은 인프라 제공자이다. + 그의 역할은 여러 개별 클러스터가 다수의 테넌트를 제공할 수 있도록 인프라를 관리하고 유지하는 것이다. + 그는 단일 테넌트에 얽매이지 않고, + 모든 테넌트를 집합적으로 고려한다. + +- **Chihiro** (그들/그들의)은 >클러스터 운영자이다. + 그들의 역할은 단일 클러스터를 관리하여 여러 사용자의 요구를 충족하도록 하는 것이다. + Chihiro는 클러스터의 단일 사용자에게 얽매이지 않으며, + 클러스터가 모든 사용자를 필요에 따라 지원하도록 해야 한다. + +- **Ana** (그녀/그녀의)은 애플리케이션 개발자이다. + Ana는 게이트웨이 API 역할 중 유일한 위치에 있다. + 그녀의 초점은 애플리케이션이 제공해야 하는 비즈니스 요구에 있으며, + 쿠버네티스나 게이트웨이 API 자체가 아니다. + 실제로, Ana는 게이트웨이 API와 쿠버네티스를 일을 완수하는 데 방해가 되는 순수한 마찰로 볼 가능성이 높다. + +(이 세 가지에 대한 자세한 내용은 [역할과 페르소나](concepts/roles-and-personas.md)에서 +자세히 설명한다). + +Ana, Chihiro, Ian이 모든 점에서 의견이 일치하지는 않지만, +원활한 운영을 위해 협력해야 한다는 점은 분명하다. +한마디로 이것이 게이트웨이 API의 핵심 과제이다. + +### 사용 사례 + +[예제 사용 사례][사용-사례]는 역할-지향적 모델이 작동하는 모습을 보여준다. +이 모델의 유연성은 API가 매우 다른 조직 모델과 구현에 적응하면서도 +이식 가능하고 표준적인 API로 남을 수 있게 한다. + +제시된 사용 사례는 위에서 소개한 역할들을 기준으로 의도적으로 구성되었다. +궁극적으로 게이트웨이 API는 인간이 사용하도록 설계되었으며, +이는 Ana, Chihiro, Ian 각각이 API를 사용하는 목적에 맞아야 함을 의미한다. + +[사용-사례]:concepts/use-cases.md + +## 게이트웨이 API와 API 게이트웨이의 차이점은 무엇인가? + +[API 게이트웨이](https://glossary.cncf.io/api-gateway/)는 +고유한 애플리케이션 API를 집계하여 한 곳에서 모두 사용 가능하게 만드는 도구이다. +이를 통해 조직은 인증, 권한 부여, 애플리케이션 간 요청 수 제한과 같은 핵심 기능을 +중앙에서 관리할 수 있다. +API 게이트웨이는 (종종 외부) API 소비자를 위한 공통 인터페이스로 기능한다. + +게이트웨이 API는 쿠버네티스에서 서비스 네트워킹을 모델링하는 일련의 쿠버네티스 리소스로 정의된 +인터페이스이다. +주요 리소스 중 하나는 `게이트웨이`로, 인스턴스화할 게이트웨이 타입(또는 클래스)과 그 설정을 선언한다. +게이트웨이 제공자로서 게이트웨이 API를 구현하여 +쿠버네티스 서비스 네트워킹을 표현력 있고 확장 가능하며 역할 지향적인 방식으로 모델링할 수 있다. + +일부 API 게이트웨이는 게이트웨이 API를 사용하여 프로그래밍할 수 있다. + +## 누가 게이트웨이 API를 개발하고 있는가? + +게이트웨이 API는 +쿠버네티스에서 서비스 네트워킹을 개선하고 표준화하기 위해 +[SIG-네트워크](https://github.com/kubernetes/community/tree/master/sig-network) +프로젝트로 개발되고 있다. +최신 게이트웨이를 지원하는 프로젝트 및 제품은 [구현 참조](implementations.md)에서 확인할 수 있다. +게이트웨이 API를 사용해 기여하거나 구현을 구축하는 데 관심이 있다면 주저하지 말고 +[참여하라!](/contributing/index.md) + +[sig-네트워크]: https://github.com/kubernetes/community/tree/master/sig-network + diff --git a/site-src/ko/js/implementations.js b/site-src/ko/js/implementations.js new file mode 100644 index 0000000000..26be6d972d --- /dev/null +++ b/site-src/ko/js/implementations.js @@ -0,0 +1,8 @@ +document$.subscribe(function() { + var tables = document.querySelectorAll("article table:not([class])") + tables.forEach(function(table) { + new Tablesort(table) + }) +}) + + diff --git a/site-src/ko/mesh/gamma.md b/site-src/ko/mesh/gamma.md new file mode 100644 index 0000000000..b482dde790 --- /dev/null +++ b/site-src/ko/mesh/gamma.md @@ -0,0 +1,48 @@ +# GAMMA 이니셔티브 (서비스 메시를 위한 게이트웨이 API) + +게이트웨이 API는 원래 클러스터 외부의 클라이언트에서 클러스터 내부의 서비스로의 트래픽을 관리하도록 설계되었다. +-- 즉, _인그레스_ 또는 [_북/남_][north/south traffic] 케이스 --. +하지만 시간이 지나면서 [서비스 메시] 사용자들의 관심에 따라 +2022년에 GAMMA(**G**ateway **A**PI for **M**esh **M**anagement and **A**dministration) 이니셔티브가 만들어졌다. +이는 게이트웨이 API가 동일한 클러스터 내에서 서비스 간 또는 +[_동/서_ 트래픽][east/west traffic]에도 사용될 수 있는 방법을 +정의하기 위함이었다. + +GAMMA 이니셔티브는 별도의 서브프로젝트가 아닌 게이트웨이 API 서브프로젝트 내의 전용 워크스트림으로, +[GAMMA 리드]가 관리한다. +GAMMA의 목표는 게이트웨이 API에 최소한의 변경만을 가하면서 +서비스 메시를 구성하는 데 게이트웨이 API를 사용할 수 있는 방법을 정의하는 것이며, +항상 게이트웨이 API의 [역할 지향적] 특성을 보존한다. +또한 기술 스택이나 프록시에 관계없이 서비스 메시 프로젝트들의 게이트웨이 API 구현 간 일관성을 옹호하기 위해 +노력한다. + +## 결과물 + +GAMMA 이니셔티브의 작업은 메시 및 메시 관련 사용 사례를 다루기 위해 게이트웨이 API 명세를 확장하거나 개선하는 +[게이트웨이 개선 제안서][geps]에 포함된다. +현재까지 이러한 변경사항들은 비교적 작았지만(때로는 상대적으로 큰 영향을 미치지만!), +앞으로도 그럴 것으로 예상한다. +게이트웨이 API 명세의 거버넌스는 게이트웨이 API 서브프로젝트의 메인테이너들에게만 남아 +있다. + +GAMMA 이니셔티브의 이상적인 최종 결과는 +서비스 메시 사용 사례가 게이트웨이 API의 일급 관심사가 되는 것이며, +이 시점에는 더 이상 별도의 이니셔티브가 필요하지 않을 것이다. + +## 기여 + +모든 수준의 기여자를 환영한다! +게이트웨이 API와 GAMMA에 [기여할 수 있는 다양한 방법][contributor-ladder]이 있으며 +이는 기술적인 것과 비기술적인 것 모두를 포함한다. + +시작하는 가장 간단한 방법은 정기적으로 열리는 게이트웨이 API [회의] 중 하나에 +참석하는 것이다. + +[north/south traffic]:../concepts/glossary.md#northsouth-traffic +[서비스 메시]:../concepts/glossary.md#service-mesh +[east/west traffic]:../concepts/glossary.md#eastwest-traffic +[역할 지향적]:../concepts/roles-and-personas.md +[geps]:../geps/overview.md +[contributor-ladder]:../contributing/contributor-ladder.md +[회의]:../contributing/index.md/#meetings +[GAMMA 리드]:https://github.com/kubernetes-sigs/gateway-api/blob/main/OWNERS_ALIASES#L23 diff --git a/site-src/ko/mesh/index.md b/site-src/ko/mesh/index.md new file mode 100644 index 0000000000..3d95227042 --- /dev/null +++ b/site-src/ko/mesh/index.md @@ -0,0 +1,162 @@ + +# 서비스 메시를 위한 게이트웨이 API + +??? success "v1.1.0부터 표준 채널" + + 서비스 메시 사용 사례를 지원하기 위한 [GAMMA 이니셔티브](gamma.md) 작업은 + v1.1.0부터 표준 채널에 포함되었으며 GA로 간주된다. + 자세한 정보는 [버전 관리 가이드](../concepts/versioning.md)를 참조하라. + +"[GAMMA 이니셔티브](gamma.md)"는 게이트웨이 API가 서비스 메시에서 +어떻게 사용될 수 있는지를 정의하는 그룹을 의미한다. +현재까지 이 그룹은 비교적 작은 변경사항으로 게이트웨이 API에서 서비스 메시 지원을 정의할 수 있었다. +GAMMA가 현재까지 도입한 가장 중요한 변경사항은 서비스 메시를 구성할 때 +개별 라우트 리소스([HTTPRoute] 등)가 [서비스 리소스와 직접 연결](#gateway-api-for-mesh)된다는 +것이다. + +이는 주로 클러스터에서 일반적으로 하나의 메시만 활성화되므로 +메시 작업 시 [게이트웨이]와 [게이트웨이 클래스] 리소스가 사용되지 않기 때문이다. +결과적으로 서비스 리소스가 라우팅 정보를 위한 가장 범용적인 바인딩 지점으로 남게 +된다. + +서비스 리소스는 불행히도 복잡하며 여러 오버로드되거나 명세가 부족한 측면이 있기 때문에, +GAMMA는 [서비스 _프론트엔드_ 와 _백엔드_ 측면][service-facets]을 공식적으로 정의하는 것이 중요하다고 판단했다. +간단히 말하면, + +- 서비스 프론트엔드는 그 이름과 클러스터 IP이고, +- 서비스 백엔드는 엔드포인트 IP들의 집합이다. + +이러한 구분은 게이트웨이 API가 서비스를 크게 복제하는 새로운 리소스를 요구하지 않으면서도 +메시 내에서 라우팅이 어떻게 작동하는지 정확하게 설명하는 데 +도움이 된다. + +[게이트웨이 클래스]: ../api-types/gatewayclass.md +[게이트웨이]: ../api-types/gateway.md +[HTTPRoute]: ../api-types/httproute.md +[TCPRoute]: ../concepts/api-overview.md#tcproute-and-udproute +[Service]: https://kubernetes.io/docs/concepts/services-networking/service/ +[service-mesh]:../concepts/glossary.md#service-mesh +[service-facets]:service-facets.md + +## 라우트와 서비스 연결 + +GAMMA는 개별 라우트 리소스가 서비스에 직접 연결되어 +_해당 서비스로 향하는 모든 트래픽에 적용될 구성_ 을 +나타낸다고 명시한다. + +하나 이상의 라우트가 서비스에 연결되면 +**최소 하나 이상의 라우트와 일치하지 않는 요청은 거부된다**. +라우트가 서비스에 연결되지 않은 경우, +해당 서비스에 대한 요청은 단순히 메시의 기본 동작에 따라 진행된다 +(일반적으로 메시가 없는 것처럼 요청이 전달됨). + +주어진 서비스에 어떤 라우트가 연결되는지는 +라우트 자체에서 제어한다(쿠버네티스 RBAC와 함께 작동). +라우트는 게이트웨이가 아닌 서비스를 지정하는 `parentRef`를 단순히 명시한다. + +```yaml +kind: HTTPRoute +metadata: + name: smiley-route + namespace: faces +spec: + parentRefs: + - name: smiley + kind: Service + group: core + port: 80 + rules: + ... +``` + +!!! note "진행 중인 작업" + + 프로듀서 라우트와 컨슈머 라우트 간의 관계에 대한 작업이 + 진행 중이다. + +라우트의 네임스페이스와 서비스의 네임스페이스 간의 관계가 +중요하다. + +- 동일한 네임스페이스 + + 서비스와 동일한 네임스페이스에 있는 라우트를 [프로듀서 라우트]라고 하는데, + 이는 일반적으로 워크로드의 생성자가 워크로드의 허용 가능한 사용을 정의하기 위해생성하기 때문이다 + (예를 들어, [Ana]가 워크로드와 라우트를 모두 배포하는 경우). + 모든 네임스페이스의 워크로드 클라이언트로부터의 모든 요청이 + 이 라우트의 영향을 받는다. + + 위에 표시된 라우트는 프로듀서 라우트이다. + +- 다른 네임스페이스 + + 서비스와 다른 네임스페이스에 있는 라우트를 [컨슈머 라우트]라고 한다. + 일반적으로 이는 주어진 워크로드의 소비자가 해당 워크로드에 대한 요청 방식을 개선하기 위한 라우트이다 + (예를 들어, 해당 소비자의 워크로드 사용에 대한 사용자 정의 타임아웃 구성). + 이 라우트는 라우트와 동일한 네임스페이스의 워크로드로부터의 요청에만 + 영향을 준다. + + 예를 들어, 아래의 HTTPRoute는 `fast-clients` 네임스페이스에 있는 `smiley` 워크로드의 모든 클라이언트가 + 100ms 타임아웃을 갖도록 한다. + + ```yaml + kind: HTTPRoute + metadata: + name: smiley-route + namespace: fast-clients + spec: + parentRefs: + - name: smiley + namespace: faces + kind: Service + group: core + port: 80 + rules: + ... + timeouts: + request: 100ms + ``` + +서비스에 바인딩된 라우트에 대해 중요한 참고 사항은 +단일 네임스페이스 내에서 동일한 서비스에 대한 여러 라우트(프로듀서 라우트든 컨슈머 라우트든)가 +게이트웨이 API [라우트 병합 규칙]에 따라 결합된다는 것이다. +따라서 현재 동일한 네임스페이스 내의 여러 소비자에 대해 구별되는 컨슈머 라우트를 정의하는 것은 +불가능하다. + +예를 들어, `blender` 워크로드와 `mixer` 워크로드가 모두 `foodprep` 네임스페이스에 있고, +둘 다 동일한 서비스를 사용하여 `oven` 워크로드를 호출하는 경우, +현재 `blender`와 `mixer`가 HTTPRoute를 사용하여 `oven` 워크로드 호출에 대해 +서로 다른 타임아웃을 설정하는 것은 불가능하다. +이를 허용하려면 `blender`와 `mixer`를 별도의 네임스페이스로 이동해야 한다. + +[Ana]:../concepts/roles-and-personas.md#ana +[프로듀서 라우트]:../concepts/glossary.md#producer-route +[컨슈머 라우트]:../concepts/glossary.md#consumer-route +[서비스 메시]:../concepts/glossary.md#service-mesh +[라우트 병합 규칙]:../api-types/httproute.md#merging + +## 요청 흐름 + +GAMMA 호환 메시가 사용될 때 일반적인 [동/서] API 요청 흐름은 다음과 +같다. + +1. 클라이언트 워크로드가 로 요청을 한다. +2. 메시 데이터 플레인이 요청을 가로채고 이를 네임스페이스 `ns`의 서비스 `foo`에 대한 트래픽으로 + 식별한다. +3. 데이터 플레인이 `foo` 서비스와 연결된 라우트를 찾은 다음, + + a. 연결된 라우트가 없으면 요청이 항상 허용되고, + `foo` 워크로드 자체가 대상 워크로드로 간주된다. + + b. 연결된 라우트가 있고 요청이 그 중 최소 하나와 일치하면, + 가장 높은 우선순위의 일치하는 라우트의 `backendRefs`가 대상 워크로드를 선택하는 데 + 사용된다. + + c. 연결된 라우트가 있지만 요청이 그 중 어느 것과도 일치하지 않으면 요청이 + 거부된다. + +6. 데이터 플레인이 대상 워크로드로 요청을 라우팅한다 + (대부분 [엔드포인트 라우팅]을 사용하지만 [서비스 라우팅]을 사용할 수도 있다). + +[동/서]:../concepts/glossary.md#eastwest-traffic +[엔드포인트 라우팅]:../concepts/glossary.md#endpoint-routing +[서비스 라우팅]:../concepts/glossary.md#service-routing diff --git a/site-src/ko/mesh/service-facets.md b/site-src/ko/mesh/service-facets.md new file mode 100644 index 0000000000..36adc2350d --- /dev/null +++ b/site-src/ko/mesh/service-facets.md @@ -0,0 +1,50 @@ +# 서비스의 다양한 측면들 + +쿠버네티스 [서비스] 리소스는 사람들이 흔히 인식하는 것보다 훨씬 복잡하다. +서비스를 생성할 때 일반적으로 클러스터 머신은 다음을 수행한다. + +- 서비스 자체에 대한 클러스터 전역 IP 주소를 할당한다(_클러스터 IP_). +- 클러스터 IP로 해석되는 서비스용 DNS 이름을 할당한다(_DNS 이름_). +- 서비스의 셀렉터에 의해 선택된 각 파드에 할당된 개별 클러스터 전역 IP 주소(_엔드포인트 IP들_)를 + 수집하여 서비스의 Endpoints 또는 EndpointSlices에 + 포함시킨다. +- 클러스터 IP로의 트래픽이 모든 엔드포인트 IP에 걸쳐 로드 밸런싱되도록 네트워크를 + 구성한다. + +불행히도 이러한 구현 세부사항들은 게이트웨이 API가 서비스 메시에서 어떻게 작동할 수 있는지를 고려할 때 +매우 중요해진다! + +[GAMMA 이니셔티브][gamma] 작업에서는 서비스를 두 개의 별도 _측면_ 으로 구성된 것으로 간주하는 것이 +유용하다는 것을 알게 되었다. + +- 서비스의 **프론트엔드**는 클러스터 IP와 DNS 이름의 + 조합이다. + +- 서비스의 **백엔드**는 엔드포인트 IP들의 집합이다. + (파드들은 서비스 백엔드의 일부가 아니지만, + 물론 엔드포인트 IP들과 강하게 연관되어 있다.) + +측면 간의 구분이 중요한 이유는 +[게이트웨이](../api-types/gateway.md)와 [메시](index.md) 각각이 +주어진 서비스를 언급하는 요청을 서비스의 프론트엔드로 보낼지 백엔드로 보낼지 결정해야 하기 +때문이다. + +- 요청을 서비스의 프론트엔드로 보내는 것(_서비스 라우팅_)은 + 어떤 엔드포인트 IP를 사용할지에 대한 결정을 + 기반 네트워크 인프라(`kube-proxy`, 서비스 메시, 또는 다른 것일 수 있음)에 + 맡긴다. + +- 요청을 서비스의 백엔드로 보내는 것(_엔드포인트 라우팅_)은 + 보다 고급 로드 밸런싱 결정을 가능하게 하기 위해 종종 필요하다 + (예를 들어, 스티키 세션을 구현하는 게이트웨이). + +서비스 라우팅이 [Ana]의 라우팅 개념에 가장 직접적으로 맞을 수 있지만, +[북/남]과 [동/서 트래픽] 모두에 게이트웨이 API를 사용할 때는 엔드포인트 라우팅이 더 예측 가능할 수 있다. +[GAMMA 이니셔티브][gamma]는 이 사용 사례에 대한 지침을 공식화하는 작업을 +진행하고 있다. + +[서비스]: https://kubernetes.io/docs/concepts/services-networking/service/ +[북/남]:../concepts/glossary.md#northsouth-traffic +[동/서 트래픽]:../concepts/glossary.md#eastwest-traffic +[gamma]:gamma.md +[Ana]:../concepts/roles-and-personas.md#ana diff --git a/site-src/ko/overrides/partials/copyright.html b/site-src/ko/overrides/partials/copyright.html new file mode 100644 index 0000000000..bb55bb04a9 --- /dev/null +++ b/site-src/ko/overrides/partials/copyright.html @@ -0,0 +1,40 @@ + + + + diff --git a/site-src/ko/overrides/partials/header.html b/site-src/ko/overrides/partials/header.html new file mode 100644 index 0000000000..07b787a4dc --- /dev/null +++ b/site-src/ko/overrides/partials/header.html @@ -0,0 +1,117 @@ + + + +{% set class = "md-header" %} +{% if "navigation.tabs.sticky" in features %} + {% set class = class ~ " md-header--shadow md-header--lifted" %} +{% elif "navigation.tabs" not in features %} + {% set class = class ~ " md-header--shadow" %} +{% endif %} + + +
+ + + + {% if "navigation.tabs.sticky" in features %} + {% if "navigation.tabs" in features %} + {% include "partials/tabs.html" %} + {% endif %} + {% endif %} +
diff --git a/site-src/ko/reference/images/policy-hierarchy.png b/site-src/ko/reference/images/policy-hierarchy.png new file mode 100644 index 0000000000..593543d2df Binary files /dev/null and b/site-src/ko/reference/images/policy-hierarchy.png differ diff --git a/site-src/ko/reference/images/referencepolicy.png b/site-src/ko/reference/images/referencepolicy.png new file mode 100644 index 0000000000..e211764a8b Binary files /dev/null and b/site-src/ko/reference/images/referencepolicy.png differ diff --git a/site-src/ko/reference/policy-attachment.md b/site-src/ko/reference/policy-attachment.md new file mode 100644 index 0000000000..67c9d77179 --- /dev/null +++ b/site-src/ko/reference/policy-attachment.md @@ -0,0 +1,17 @@ +# Metaresources and Policy Attachment + +Gateway API defines a Kubernetes object that _augments_ the behavior of an object +in a standard way as a _Metaresource_. ReferenceGrant +is an example of this general type of metaresource, but it is far from the only +one. + +Gateway API also defines a pattern called _Policy Attachment_, which augments +the behavior of an object to add additional settings that can't be described +within the spec of that object. + +A "Policy Attachment" is a specific type of _metaresource_ that can affect specific +settings across either one object (this is "Direct Policy Attachment"), or objects +in a hierarchy (this is "Inherited Policy Attachment"). + +This pattern is EXPERIMENTAL, and is described in [GEP-713](../geps/gep-713/index.md). +Please see that document for technical details. diff --git a/site-src/ko/reference/spec.md b/site-src/ko/reference/spec.md new file mode 100644 index 0000000000..2a2be734e2 --- /dev/null +++ b/site-src/ko/reference/spec.md @@ -0,0 +1,3308 @@ +# API Reference + +## Packages +- [gateway.networking.k8s.io/v1](#gatewaynetworkingk8siov1) +- [gateway.networking.k8s.io/v1alpha2](#gatewaynetworkingk8siov1alpha2) +- [gateway.networking.k8s.io/v1alpha3](#gatewaynetworkingk8siov1alpha3) +- [gateway.networking.k8s.io/v1beta1](#gatewaynetworkingk8siov1beta1) + + +## gateway.networking.k8s.io/v1 + +Package v1 contains API Schema definitions for the gateway.networking.k8s.io +API group. + + +### Resource Types +- [GRPCRoute](#grpcroute) +- [Gateway](#gateway) +- [GatewayClass](#gatewayclass) +- [HTTPRoute](#httproute) + + + +#### AbsoluteURI + +_Underlying type:_ _string_ + +The AbsoluteURI MUST NOT be a relative URI, and it MUST follow the URI syntax and +encoding rules specified in RFC3986. The AbsoluteURI MUST include both a +scheme (e.g., "http" or "spiffe") and a scheme-specific-part. URIs that +include an authority MUST include a fully qualified domain name or +IP address as the host. + The below regex is taken from the regex section in RFC 3986 with a slight modification to enforce a full URI and not relative. + +_Validation:_ +- MaxLength: 253 +- MinLength: 1 +- Pattern: `^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?` + +_Appears in:_ +- [HTTPCORSFilter](#httpcorsfilter) +- [SubjectAltName](#subjectaltname) + + + +#### AddressType + +_Underlying type:_ _string_ + +AddressType defines how a network address is represented as a text string. +This may take two possible forms: + +* A predefined CamelCase string identifier (currently limited to `IPAddress` or `Hostname`) +* A domain-prefixed string identifier (like `acme.io/CustomAddressType`) + +Values `IPAddress` and `Hostname` have Extended support. + +The `NamedAddress` value has been deprecated in favor of implementation +specific domain-prefixed strings. + +All other values, including domain-prefixed values have Implementation-specific support, +which are used in implementation-specific behaviors. Support for additional +predefined CamelCase identifiers may be added in future releases. + +_Validation:_ +- MaxLength: 253 +- MinLength: 1 +- Pattern: `^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` + +_Appears in:_ +- [GatewaySpecAddress](#gatewayspecaddress) +- [GatewayStatusAddress](#gatewaystatusaddress) + +| Field | Description | +| --- | --- | +| `IPAddress` | A textual representation of a numeric IP address. IPv4
addresses must be in dotted-decimal form. IPv6 addresses
must be in a standard IPv6 text representation
(see [RFC 5952](https://tools.ietf.org/html/rfc5952)).
This type is intended for specific addresses. Address ranges are not
supported (e.g. you cannot use a CIDR range like 127.0.0.0/24 as an
IPAddress).
Support: Extended
| +| `Hostname` | A Hostname represents a DNS based ingress point. This is similar to the
corresponding hostname field in Kubernetes load balancer status. For
example, this concept may be used for cloud load balancers where a DNS
name is used to expose a load balancer.
Support: Extended
| +| `NamedAddress` | A NamedAddress provides a way to reference a specific IP address by name.
For example, this may be a name or other unique identifier that refers
to a resource on a cloud provider such as a static IP.
The `NamedAddress` type has been deprecated in favor of implementation
specific domain-prefixed strings.
Support: Implementation-specific
| + + +#### AllowedListeners + + + +AllowedListeners defines which ListenerSets can be attached to this Gateway. + + + +_Appears in:_ +- [GatewaySpec](#gatewayspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `namespaces` _[ListenerNamespaces](#listenernamespaces)_ | Namespaces defines which namespaces ListenerSets can be attached to this Gateway.
While this feature is experimental, the default value is to allow no ListenerSets. | \{ from:None \} | | + + +#### AllowedRoutes + + + +AllowedRoutes defines which Routes may be attached to this Listener. + + + +_Appears in:_ +- [Listener](#listener) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `namespaces` _[RouteNamespaces](#routenamespaces)_ | Namespaces indicates namespaces from which Routes may be attached to this
Listener. This is restricted to the namespace of this Gateway by default.
Support: Core | \{ from:Same \} | | +| `kinds` _[RouteGroupKind](#routegroupkind) array_ | Kinds specifies the groups and kinds of Routes that are allowed to bind
to this Gateway Listener. When unspecified or empty, the kinds of Routes
selected are determined using the Listener protocol.
A RouteGroupKind MUST correspond to kinds of Routes that are compatible
with the application protocol specified in the Listener's Protocol field.
If an implementation does not support or recognize this resource type, it
MUST set the "ResolvedRefs" condition to False for this Listener with the
"InvalidRouteKinds" reason.
Support: Core | | MaxItems: 8
| + + +#### AnnotationKey + +_Underlying type:_ _string_ + +AnnotationKey is the key of an annotation in Gateway API. This is used for +validation of maps such as TLS options. This matches the Kubernetes +"qualified name" validation that is used for annotations and other common +values. + +Valid values include: + +* example +* example.com +* example.com/path +* example.com/path.html + +Invalid values include: + +* example~ - "~" is an invalid character +* example.com. - cannot start or end with "." + +_Validation:_ +- MaxLength: 253 +- MinLength: 1 +- Pattern: `^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$` + +_Appears in:_ +- [BackendTLSPolicySpec](#backendtlspolicyspec) +- [GatewayInfrastructure](#gatewayinfrastructure) +- [GatewayTLSConfig](#gatewaytlsconfig) + + + +#### AnnotationValue + +_Underlying type:_ _string_ + +AnnotationValue is the value of an annotation in Gateway API. This is used +for validation of maps such as TLS options. This roughly matches Kubernetes +annotation validation, although the length validation in that case is based +on the entire size of the annotations struct. + +_Validation:_ +- MaxLength: 4096 +- MinLength: 0 + +_Appears in:_ +- [BackendTLSPolicySpec](#backendtlspolicyspec) +- [GatewayInfrastructure](#gatewayinfrastructure) +- [GatewayTLSConfig](#gatewaytlsconfig) + + + +#### BackendObjectReference + + + +BackendObjectReference defines how an ObjectReference that is +specific to BackendRef. It includes a few additional fields and features +than a regular ObjectReference. + +Note that when a namespace different than the local namespace is specified, a +ReferenceGrant object is required in the referent namespace to allow that +namespace's owner to accept the reference. See the ReferenceGrant +documentation for details. + +The API object must be valid in the cluster; the Group and Kind must +be registered in the cluster for this reference to be valid. + +References to objects with invalid Group and Kind are not valid, and must +be rejected by the implementation, with appropriate Conditions set +on the containing object. + + + +_Appears in:_ +- [BackendRef](#backendref) +- [GRPCBackendRef](#grpcbackendref) +- [HTTPBackendRef](#httpbackendref) +- [HTTPRequestMirrorFilter](#httprequestmirrorfilter) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent. For example, "gateway.networking.k8s.io".
When unspecified or empty string, core API group is inferred. | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent. For example
"Service".
Defaults to "Service" when not specified.
ExternalName services can refer to CNAME DNS records that may live
outside of the cluster and as such are difficult to reason about in
terms of conformance. They also may not be safe to forward to (see
CVE-2021-25740 for more information). Implementations SHOULD NOT
support ExternalName Services.
Support: Core (Services with a type other than ExternalName)
Support: Implementation-specific (Services with type ExternalName) | Service | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. | | MaxLength: 253
MinLength: 1
| +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the backend. When unspecified, the local
namespace is inferred.
Note that when a namespace different than the local namespace is specified,
a ReferenceGrant object is required in the referent namespace to allow that
namespace's owner to accept the reference. See the ReferenceGrant
documentation for details.
Support: Core | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| +| `port` _[PortNumber](#portnumber)_ | Port specifies the destination port number to use for this resource.
Port is required when the referent is a Kubernetes Service. In this
case, the port number is the service port number, not the target port.
For other resources, destination port might be derived from the referent
resource or this field. | | Maximum: 65535
Minimum: 1
| + + +#### BackendRef + + + +BackendRef defines how a Route should forward a request to a Kubernetes +resource. + +Note that when a namespace different than the local namespace is specified, a +ReferenceGrant object is required in the referent namespace to allow that +namespace's owner to accept the reference. See the ReferenceGrant +documentation for details. + + + +When the BackendRef points to a Kubernetes Service, implementations SHOULD +honor the appProtocol field if it is set for the target Service Port. + +Implementations supporting appProtocol SHOULD recognize the Kubernetes +Standard Application Protocols defined in KEP-3726. + +If a Service appProtocol isn't specified, an implementation MAY infer the +backend protocol through its own means. Implementations MAY infer the +protocol from the Route type referring to the backend Service. + +If a Route is not able to send traffic to the backend using the specified +protocol then the backend is considered invalid. Implementations MUST set the +"ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. + + + +Note that when the BackendTLSPolicy object is enabled by the implementation, +there are some extra rules about validity to consider here. See the fields +where this struct is used for more information about the exact behavior. + + + +_Appears in:_ +- [GRPCBackendRef](#grpcbackendref) +- [HTTPBackendRef](#httpbackendref) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent. For example, "gateway.networking.k8s.io".
When unspecified or empty string, core API group is inferred. | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent. For example
"Service".
Defaults to "Service" when not specified.
ExternalName services can refer to CNAME DNS records that may live
outside of the cluster and as such are difficult to reason about in
terms of conformance. They also may not be safe to forward to (see
CVE-2021-25740 for more information). Implementations SHOULD NOT
support ExternalName Services.
Support: Core (Services with a type other than ExternalName)
Support: Implementation-specific (Services with type ExternalName) | Service | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. | | MaxLength: 253
MinLength: 1
| +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the backend. When unspecified, the local
namespace is inferred.
Note that when a namespace different than the local namespace is specified,
a ReferenceGrant object is required in the referent namespace to allow that
namespace's owner to accept the reference. See the ReferenceGrant
documentation for details.
Support: Core | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| +| `port` _[PortNumber](#portnumber)_ | Port specifies the destination port number to use for this resource.
Port is required when the referent is a Kubernetes Service. In this
case, the port number is the service port number, not the target port.
For other resources, destination port might be derived from the referent
resource or this field. | | Maximum: 65535
Minimum: 1
| +| `weight` _integer_ | Weight specifies the proportion of requests forwarded to the referenced
backend. This is computed as weight/(sum of all weights in this
BackendRefs list). For non-zero values, there may be some epsilon from
the exact proportion defined here depending on the precision an
implementation supports. Weight is not a percentage and the sum of
weights does not need to equal 100.
If only one backend is specified and it has a weight greater than 0, 100%
of the traffic is forwarded to that backend. If weight is set to 0, no
traffic should be forwarded for this entry. If unspecified, weight
defaults to 1.
Support for this field varies based on the context where used. | 1 | Maximum: 1e+06
Minimum: 0
| + + +#### CommonRouteSpec + + + +CommonRouteSpec defines the common attributes that all Routes MUST include +within their spec. + + + +_Appears in:_ +- [GRPCRouteSpec](#grpcroutespec) +- [HTTPRouteSpec](#httproutespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `parentRefs` _[ParentReference](#parentreference) array_ | ParentRefs references the resources (usually Gateways) that a Route wants
to be attached to. Note that the referenced parent resource needs to
allow this for the attachment to be complete. For Gateways, that means
the Gateway needs to allow attachment from Routes of this kind and
namespace. For Services, that means the Service must either be in the same
namespace for a "producer" route, or the mesh implementation must support
and allow "consumer" routes for the referenced Service. ReferenceGrant is
not applicable for governing ParentRefs to Services - it is not possible to
create a "producer" route for a Service in a different namespace from the
Route.
There are two kinds of parent resources with "Core" support:
* Gateway (Gateway conformance profile)
* Service (Mesh conformance profile, ClusterIP Services only)
This API may be extended in the future to support additional kinds of parent
resources.
ParentRefs must be _distinct_. This means either that:
* They select different objects. If this is the case, then parentRef
entries are distinct. In terms of fields, this means that the
multi-part key defined by `group`, `kind`, `namespace`, and `name` must
be unique across all parentRef entries in the Route.
* They do not select different objects, but for each optional field used,
each ParentRef that selects the same object must set the same set of
optional fields to different values. If one ParentRef sets a
combination of optional fields, all must set the same combination.
Some examples:
* If one ParentRef sets `sectionName`, all ParentRefs referencing the
same object must also set `sectionName`.
* If one ParentRef sets `port`, all ParentRefs referencing the same
object must also set `port`.
* If one ParentRef sets `sectionName` and `port`, all ParentRefs
referencing the same object must also set `sectionName` and `port`.
It is possible to separately reference multiple distinct objects that may
be collapsed by an implementation. For example, some implementations may
choose to merge compatible Gateway Listeners together. If that is the
case, the list of routes attached to those resources should also be
merged.
Note that for ParentRefs that cross namespace boundaries, there are specific
rules. Cross-namespace references are only valid if they are explicitly
allowed by something in the namespace they are referring to. For example,
Gateway has the AllowedRoutes field, and ReferenceGrant provides a
generic way to enable other kinds of cross-namespace reference.

ParentRefs from a Route to a Service in the same namespace are "producer"
routes, which apply default routing rules to inbound connections from
any namespace to the Service.
ParentRefs from a Route to a Service in a different namespace are
"consumer" routes, and these routing rules are only applied to outbound
connections originating from the same namespace as the Route, for which
the intended destination of the connections are a Service targeted as a
ParentRef of the Route.




| | MaxItems: 32
| + + +#### CookieConfig + + + +CookieConfig defines the configuration for cookie-based session persistence. + + + +_Appears in:_ +- [SessionPersistence](#sessionpersistence) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `lifetimeType` _[CookieLifetimeType](#cookielifetimetype)_ | LifetimeType specifies whether the cookie has a permanent or
session-based lifetime. A permanent cookie persists until its
specified expiry time, defined by the Expires or Max-Age cookie
attributes, while a session cookie is deleted when the current
session ends.
When set to "Permanent", AbsoluteTimeout indicates the
cookie's lifetime via the Expires or Max-Age cookie attributes
and is required.
When set to "Session", AbsoluteTimeout indicates the
absolute lifetime of the cookie tracked by the gateway and
is optional.
Defaults to "Session".
Support: Core for "Session" type
Support: Extended for "Permanent" type | Session | Enum: [Permanent Session]
| + + +#### CookieLifetimeType + +_Underlying type:_ _string_ + + + +_Validation:_ +- Enum: [Permanent Session] + +_Appears in:_ +- [CookieConfig](#cookieconfig) + +| Field | Description | +| --- | --- | +| `Session` | SessionCookieLifetimeType specifies the type for a session
cookie.
Support: Core
| +| `Permanent` | PermanentCookieLifetimeType specifies the type for a permanent
cookie.
Support: Extended
| + + +#### Duration + +_Underlying type:_ _string_ + +Duration is a string value representing a duration in time. The format is as specified +in GEP-2257, a strict subset of the syntax parsed by Golang time.ParseDuration. + +_Validation:_ +- Pattern: `^([0-9]{1,5}(h|m|s|ms)){1,4}$` + +_Appears in:_ +- [HTTPRouteRetry](#httprouteretry) +- [HTTPRouteTimeouts](#httproutetimeouts) +- [SessionPersistence](#sessionpersistence) + + + +#### FeatureName + +_Underlying type:_ _string_ + +FeatureName is used to describe distinct features that are covered by +conformance tests. + + + +_Appears in:_ +- [SupportedFeature](#supportedfeature) + + + +#### Fraction + + + + + + + +_Appears in:_ +- [HTTPRequestMirrorFilter](#httprequestmirrorfilter) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `numerator` _integer_ | | | Minimum: 0
| +| `denominator` _integer_ | | 100 | Minimum: 1
| + + +#### FromNamespaces + +_Underlying type:_ _string_ + +FromNamespaces specifies namespace from which Routes/ListenerSets may be attached to a +Gateway. + + + +_Appears in:_ +- [ListenerNamespaces](#listenernamespaces) +- [RouteNamespaces](#routenamespaces) + +| Field | Description | +| --- | --- | +| `All` | Routes/ListenerSets in all namespaces may be attached to this Gateway.
| +| `Selector` | Only Routes/ListenerSets in namespaces selected by the selector may be attached to
this Gateway.
| +| `Same` | Only Routes/ListenerSets in the same namespace as the Gateway may be attached to this
Gateway.
| +| `None` | No Routes/ListenerSets may be attached to this Gateway.
| + + +#### FrontendTLSValidation + + + +FrontendTLSValidation holds configuration information that can be used to validate +the frontend initiating the TLS connection + + + +_Appears in:_ +- [GatewayTLSConfig](#gatewaytlsconfig) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `caCertificateRefs` _[ObjectReference](#objectreference) array_ | CACertificateRefs contains one or more references to
Kubernetes objects that contain TLS certificates of
the Certificate Authorities that can be used
as a trust anchor to validate the certificates presented by the client.
A single CA certificate reference to a Kubernetes ConfigMap
has "Core" support.
Implementations MAY choose to support attaching multiple CA certificates to
a Listener, but this behavior is implementation-specific.
Support: Core - A single reference to a Kubernetes ConfigMap
with the CA certificate in a key named `ca.crt`.
Support: Implementation-specific (More than one reference, or other kinds
of resources).
References to a resource in a different namespace are invalid UNLESS there
is a ReferenceGrant in the target namespace that allows the certificate
to be attached. If a ReferenceGrant does not allow this reference, the
"ResolvedRefs" condition MUST be set to False for this listener with the
"RefNotPermitted" reason. | | MaxItems: 8
MinItems: 1
| + + +#### GRPCBackendRef + + + +GRPCBackendRef defines how a GRPCRoute forwards a gRPC request. + +Note that when a namespace different than the local namespace is specified, a +ReferenceGrant object is required in the referent namespace to allow that +namespace's owner to accept the reference. See the ReferenceGrant +documentation for details. + + + +When the BackendRef points to a Kubernetes Service, implementations SHOULD +honor the appProtocol field if it is set for the target Service Port. + +Implementations supporting appProtocol SHOULD recognize the Kubernetes +Standard Application Protocols defined in KEP-3726. + +If a Service appProtocol isn't specified, an implementation MAY infer the +backend protocol through its own means. Implementations MAY infer the +protocol from the Route type referring to the backend Service. + +If a Route is not able to send traffic to the backend using the specified +protocol then the backend is considered invalid. Implementations MUST set the +"ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. + + + + + +_Appears in:_ +- [GRPCRouteRule](#grpcrouterule) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent. For example, "gateway.networking.k8s.io".
When unspecified or empty string, core API group is inferred. | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent. For example
"Service".
Defaults to "Service" when not specified.
ExternalName services can refer to CNAME DNS records that may live
outside of the cluster and as such are difficult to reason about in
terms of conformance. They also may not be safe to forward to (see
CVE-2021-25740 for more information). Implementations SHOULD NOT
support ExternalName Services.
Support: Core (Services with a type other than ExternalName)
Support: Implementation-specific (Services with type ExternalName) | Service | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. | | MaxLength: 253
MinLength: 1
| +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the backend. When unspecified, the local
namespace is inferred.
Note that when a namespace different than the local namespace is specified,
a ReferenceGrant object is required in the referent namespace to allow that
namespace's owner to accept the reference. See the ReferenceGrant
documentation for details.
Support: Core | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| +| `port` _[PortNumber](#portnumber)_ | Port specifies the destination port number to use for this resource.
Port is required when the referent is a Kubernetes Service. In this
case, the port number is the service port number, not the target port.
For other resources, destination port might be derived from the referent
resource or this field. | | Maximum: 65535
Minimum: 1
| +| `weight` _integer_ | Weight specifies the proportion of requests forwarded to the referenced
backend. This is computed as weight/(sum of all weights in this
BackendRefs list). For non-zero values, there may be some epsilon from
the exact proportion defined here depending on the precision an
implementation supports. Weight is not a percentage and the sum of
weights does not need to equal 100.
If only one backend is specified and it has a weight greater than 0, 100%
of the traffic is forwarded to that backend. If weight is set to 0, no
traffic should be forwarded for this entry. If unspecified, weight
defaults to 1.
Support for this field varies based on the context where used. | 1 | Maximum: 1e+06
Minimum: 0
| +| `filters` _[GRPCRouteFilter](#grpcroutefilter) array_ | Filters defined at this level MUST be executed if and only if the
request is being forwarded to the backend defined here.
Support: Implementation-specific (For broader support of filters, use the
Filters field in GRPCRouteRule.) | | MaxItems: 16
| + + +#### GRPCHeaderMatch + + + +GRPCHeaderMatch describes how to select a gRPC route by matching gRPC request +headers. + + + +_Appears in:_ +- [GRPCRouteMatch](#grpcroutematch) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[GRPCHeaderMatchType](#grpcheadermatchtype)_ | Type specifies how to match against the value of the header. | Exact | Enum: [Exact RegularExpression]
| +| `name` _[GRPCHeaderName](#grpcheadername)_ | Name is the name of the gRPC Header to be matched.
If multiple entries specify equivalent header names, only the first
entry with an equivalent name MUST be considered for a match. Subsequent
entries with an equivalent header name MUST be ignored. Due to the
case-insensitivity of header names, "foo" and "Foo" are considered
equivalent. | | MaxLength: 256
MinLength: 1
Pattern: `^[A-Za-z0-9!#$%&'*+\-.^_\x60\|~]+$`
| +| `value` _string_ | Value is the value of the gRPC Header to be matched. | | MaxLength: 4096
MinLength: 1
| + + +#### GRPCHeaderMatchType + +_Underlying type:_ _string_ + +GRPCHeaderMatchType specifies the semantics of how GRPC header values should +be compared. Valid GRPCHeaderMatchType values, along with their conformance +levels, are: + +* "Exact" - Core +* "RegularExpression" - Implementation Specific + +Note that new values may be added to this enum in future releases of the API, +implementations MUST ensure that unknown values will not cause a crash. + +Unknown values here MUST result in the implementation setting the Accepted +Condition for the Route to `status: False`, with a Reason of +`UnsupportedValue`. + +_Validation:_ +- Enum: [Exact RegularExpression] + +_Appears in:_ +- [GRPCHeaderMatch](#grpcheadermatch) + +| Field | Description | +| --- | --- | +| `Exact` | | +| `RegularExpression` | | + + +#### GRPCHeaderName + +_Underlying type:_ _[HeaderName](#headername)_ + + + +_Validation:_ +- MaxLength: 256 +- MinLength: 1 +- Pattern: `^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$` + +_Appears in:_ +- [GRPCHeaderMatch](#grpcheadermatch) + + + +#### GRPCMethodMatch + + + +GRPCMethodMatch describes how to select a gRPC route by matching the gRPC +request service and/or method. + +At least one of Service and Method MUST be a non-empty string. + + + +_Appears in:_ +- [GRPCRouteMatch](#grpcroutematch) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[GRPCMethodMatchType](#grpcmethodmatchtype)_ | Type specifies how to match against the service and/or method.
Support: Core (Exact with service and method specified)
Support: Implementation-specific (Exact with method specified but no service specified)
Support: Implementation-specific (RegularExpression) | Exact | Enum: [Exact RegularExpression]
| +| `service` _string_ | Value of the service to match against. If left empty or omitted, will
match any service.
At least one of Service and Method MUST be a non-empty string. | | MaxLength: 1024
| +| `method` _string_ | Value of the method to match against. If left empty or omitted, will
match all services.
At least one of Service and Method MUST be a non-empty string. | | MaxLength: 1024
| + + +#### GRPCMethodMatchType + +_Underlying type:_ _string_ + +MethodMatchType specifies the semantics of how gRPC methods and services are compared. +Valid MethodMatchType values, along with their conformance levels, are: + +* "Exact" - Core +* "RegularExpression" - Implementation Specific + +Exact methods MUST be syntactically valid: + +- Must not contain `/` character + +_Validation:_ +- Enum: [Exact RegularExpression] + +_Appears in:_ +- [GRPCMethodMatch](#grpcmethodmatch) + +| Field | Description | +| --- | --- | +| `Exact` | Matches the method or service exactly and with case sensitivity.
| +| `RegularExpression` | Matches if the method or service matches the given regular expression with
case sensitivity.
Since `"RegularExpression"` has implementation-specific conformance,
implementations can support POSIX, PCRE, RE2 or any other regular expression
dialect.
Please read the implementation's documentation to determine the supported
dialect.
| + + +#### GRPCRoute + + + +GRPCRoute provides a way to route gRPC requests. This includes the capability +to match requests by hostname, gRPC service, gRPC method, or HTTP/2 header. +Filters can be used to specify additional processing steps. Backends specify +where matching requests will be routed. + +GRPCRoute falls under extended support within the Gateway API. Within the +following specification, the word "MUST" indicates that an implementation +supporting GRPCRoute must conform to the indicated requirement, but an +implementation not supporting this route type need not follow the requirement +unless explicitly indicated. + +Implementations supporting `GRPCRoute` with the `HTTPS` `ProtocolType` MUST +accept HTTP/2 connections without an initial upgrade from HTTP/1.1, i.e. via +ALPN. If the implementation does not support this, then it MUST set the +"Accepted" condition to "False" for the affected listener with a reason of +"UnsupportedProtocol". Implementations MAY also accept HTTP/2 connections +with an upgrade from HTTP/1. + +Implementations supporting `GRPCRoute` with the `HTTP` `ProtocolType` MUST +support HTTP/2 over cleartext TCP (h2c, +https://www.rfc-editor.org/rfc/rfc7540#section-3.1) without an initial +upgrade from HTTP/1.1, i.e. with prior knowledge +(https://www.rfc-editor.org/rfc/rfc7540#section-3.4). If the implementation +does not support this, then it MUST set the "Accepted" condition to "False" +for the affected listener with a reason of "UnsupportedProtocol". +Implementations MAY also accept HTTP/2 connections with an upgrade from +HTTP/1, i.e. without prior knowledge. + + + +_Appears in:_ +- [GRPCRoute](#grpcroute) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1` | | | +| `kind` _string_ | `GRPCRoute` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[GRPCRouteSpec](#grpcroutespec)_ | Spec defines the desired state of GRPCRoute. | | | +| `status` _[GRPCRouteStatus](#grpcroutestatus)_ | Status defines the current state of GRPCRoute. | | | + + +#### GRPCRouteFilter + + + +GRPCRouteFilter defines processing steps that must be completed during the +request or response lifecycle. GRPCRouteFilters are meant as an extension +point to express processing that may be done in Gateway implementations. Some +examples include request or response modification, implementing +authentication strategies, rate-limiting, and traffic shaping. API +guarantee/conformance is defined based on the type of the filter. + + + +_Appears in:_ +- [GRPCBackendRef](#grpcbackendref) +- [GRPCRouteRule](#grpcrouterule) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[GRPCRouteFilterType](#grpcroutefiltertype)_ | Type identifies the type of filter to apply. As with other API fields,
types are classified into three conformance levels:
- Core: Filter types and their corresponding configuration defined by
"Support: Core" in this package, e.g. "RequestHeaderModifier". All
implementations supporting GRPCRoute MUST support core filters.
- Extended: Filter types and their corresponding configuration defined by
"Support: Extended" in this package, e.g. "RequestMirror". Implementers
are encouraged to support extended filters.
- Implementation-specific: Filters that are defined and supported by specific vendors.
In the future, filters showing convergence in behavior across multiple
implementations will be considered for inclusion in extended or core
conformance levels. Filter-specific configuration for such filters
is specified using the ExtensionRef field. `Type` MUST be set to
"ExtensionRef" for custom filters.
Implementers are encouraged to define custom implementation types to
extend the core API with implementation-specific behavior.
If a reference to a custom filter type cannot be resolved, the filter
MUST NOT be skipped. Instead, requests that would have been processed by
that filter MUST receive a HTTP error response.
| | Enum: [ResponseHeaderModifier RequestHeaderModifier RequestMirror ExtensionRef]
| +| `requestHeaderModifier` _[HTTPHeaderFilter](#httpheaderfilter)_ | RequestHeaderModifier defines a schema for a filter that modifies request
headers.
Support: Core | | | +| `responseHeaderModifier` _[HTTPHeaderFilter](#httpheaderfilter)_ | ResponseHeaderModifier defines a schema for a filter that modifies response
headers.
Support: Extended | | | +| `requestMirror` _[HTTPRequestMirrorFilter](#httprequestmirrorfilter)_ | RequestMirror defines a schema for a filter that mirrors requests.
Requests are sent to the specified destination, but responses from
that destination are ignored.
This filter can be used multiple times within the same rule. Note that
not all implementations will be able to support mirroring to multiple
backends.
Support: Extended | | | +| `extensionRef` _[LocalObjectReference](#localobjectreference)_ | ExtensionRef is an optional, implementation-specific extension to the
"filter" behavior. For example, resource "myroutefilter" in group
"networking.example.net"). ExtensionRef MUST NOT be used for core and
extended filters.
Support: Implementation-specific
This filter can be used multiple times within the same rule. | | | + + +#### GRPCRouteFilterType + +_Underlying type:_ _string_ + +GRPCRouteFilterType identifies a type of GRPCRoute filter. + + + +_Appears in:_ +- [GRPCRouteFilter](#grpcroutefilter) + +| Field | Description | +| --- | --- | +| `RequestHeaderModifier` | GRPCRouteFilterRequestHeaderModifier can be used to add or remove a gRPC
header from a gRPC request before it is sent to the upstream target.
Support in GRPCRouteRule: Core
Support in GRPCBackendRef: Extended
| +| `ResponseHeaderModifier` | GRPCRouteFilterRequestHeaderModifier can be used to add or remove a gRPC
header from a gRPC response before it is sent to the client.
Support in GRPCRouteRule: Core
Support in GRPCBackendRef: Extended
| +| `RequestMirror` | GRPCRouteFilterRequestMirror can be used to mirror gRPC requests to a
different backend. The responses from this backend MUST be ignored by
the Gateway.
Support in GRPCRouteRule: Extended
Support in GRPCBackendRef: Extended
| +| `ExtensionRef` | GRPCRouteFilterExtensionRef should be used for configuring custom
gRPC filters.
Support in GRPCRouteRule: Implementation-specific
Support in GRPCBackendRef: Implementation-specific
| + + +#### GRPCRouteMatch + + + +GRPCRouteMatch defines the predicate used to match requests to a given +action. Multiple match types are ANDed together, i.e. the match will +evaluate to true only if all conditions are satisfied. + +For example, the match below will match a gRPC request only if its service +is `foo` AND it contains the `version: v1` header: + +``` +matches: + - method: + type: Exact + service: "foo" + headers: + - name: "version" + value "v1" + +``` + + + +_Appears in:_ +- [GRPCRouteRule](#grpcrouterule) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `method` _[GRPCMethodMatch](#grpcmethodmatch)_ | Method specifies a gRPC request service/method matcher. If this field is
not specified, all services and methods will match. | | | +| `headers` _[GRPCHeaderMatch](#grpcheadermatch) array_ | Headers specifies gRPC request header matchers. Multiple match values are
ANDed together, meaning, a request MUST match all the specified headers
to select the route. | | MaxItems: 16
| + + +#### GRPCRouteRule + + + +GRPCRouteRule defines the semantics for matching a gRPC request based on +conditions (matches), processing it (filters), and forwarding the request to +an API object (backendRefs). + + + +_Appears in:_ +- [GRPCRouteSpec](#grpcroutespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _[SectionName](#sectionname)_ | Name is the name of the route rule. This name MUST be unique within a Route if it is set.
Support: Extended
| | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `matches` _[GRPCRouteMatch](#grpcroutematch) array_ | Matches define conditions used for matching the rule against incoming
gRPC requests. Each match is independent, i.e. this rule will be matched
if **any** one of the matches is satisfied.
For example, take the following matches configuration:
```
matches:
- method:
service: foo.bar
headers:
values:
version: 2
- method:
service: foo.bar.v2
```
For a request to match against this rule, it MUST satisfy
EITHER of the two conditions:
- service of foo.bar AND contains the header `version: 2`
- service of foo.bar.v2
See the documentation for GRPCRouteMatch on how to specify multiple
match conditions to be ANDed together.
If no matches are specified, the implementation MUST match every gRPC request.
Proxy or Load Balancer routing configuration generated from GRPCRoutes
MUST prioritize rules based on the following criteria, continuing on
ties. Merging MUST not be done between GRPCRoutes and HTTPRoutes.
Precedence MUST be given to the rule with the largest number of:
* Characters in a matching non-wildcard hostname.
* Characters in a matching hostname.
* Characters in a matching service.
* Characters in a matching method.
* Header matches.
If ties still exist across multiple Routes, matching precedence MUST be
determined in order of the following criteria, continuing on ties:
* The oldest Route based on creation timestamp.
* The Route appearing first in alphabetical order by
"\{namespace\}/\{name\}".
If ties still exist within the Route that has been given precedence,
matching precedence MUST be granted to the first matching rule meeting
the above criteria. | | MaxItems: 64
| +| `filters` _[GRPCRouteFilter](#grpcroutefilter) array_ | Filters define the filters that are applied to requests that match
this rule.
The effects of ordering of multiple behaviors are currently unspecified.
This can change in the future based on feedback during the alpha stage.
Conformance-levels at this level are defined based on the type of filter:
- ALL core filters MUST be supported by all implementations that support
GRPCRoute.
- Implementers are encouraged to support extended filters.
- Implementation-specific custom filters have no API guarantees across
implementations.
Specifying the same filter multiple times is not supported unless explicitly
indicated in the filter.
If an implementation cannot support a combination of filters, it must clearly
document that limitation. In cases where incompatible or unsupported
filters are specified and cause the `Accepted` condition to be set to status
`False`, implementations may use the `IncompatibleFilters` reason to specify
this configuration error.
Support: Core | | MaxItems: 16
| +| `backendRefs` _[GRPCBackendRef](#grpcbackendref) array_ | BackendRefs defines the backend(s) where matching requests should be
sent.
Failure behavior here depends on how many BackendRefs are specified and
how many are invalid.
If *all* entries in BackendRefs are invalid, and there are also no filters
specified in this route rule, *all* traffic which matches this rule MUST
receive an `UNAVAILABLE` status.
See the GRPCBackendRef definition for the rules about what makes a single
GRPCBackendRef invalid.
When a GRPCBackendRef is invalid, `UNAVAILABLE` statuses MUST be returned for
requests that would have otherwise been routed to an invalid backend. If
multiple backends are specified, and some are invalid, the proportion of
requests that would otherwise have been routed to an invalid backend
MUST receive an `UNAVAILABLE` status.
For example, if two backends are specified with equal weights, and one is
invalid, 50 percent of traffic MUST receive an `UNAVAILABLE` status.
Implementations may choose how that 50 percent is determined.
Support: Core for Kubernetes Service
Support: Implementation-specific for any other resource
Support for weight: Core | | MaxItems: 16
| +| `sessionPersistence` _[SessionPersistence](#sessionpersistence)_ | SessionPersistence defines and configures session persistence
for the route rule.
Support: Extended
| | | + + +#### GRPCRouteSpec + + + +GRPCRouteSpec defines the desired state of GRPCRoute + + + +_Appears in:_ +- [GRPCRoute](#grpcroute) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `parentRefs` _[ParentReference](#parentreference) array_ | ParentRefs references the resources (usually Gateways) that a Route wants
to be attached to. Note that the referenced parent resource needs to
allow this for the attachment to be complete. For Gateways, that means
the Gateway needs to allow attachment from Routes of this kind and
namespace. For Services, that means the Service must either be in the same
namespace for a "producer" route, or the mesh implementation must support
and allow "consumer" routes for the referenced Service. ReferenceGrant is
not applicable for governing ParentRefs to Services - it is not possible to
create a "producer" route for a Service in a different namespace from the
Route.
There are two kinds of parent resources with "Core" support:
* Gateway (Gateway conformance profile)
* Service (Mesh conformance profile, ClusterIP Services only)
This API may be extended in the future to support additional kinds of parent
resources.
ParentRefs must be _distinct_. This means either that:
* They select different objects. If this is the case, then parentRef
entries are distinct. In terms of fields, this means that the
multi-part key defined by `group`, `kind`, `namespace`, and `name` must
be unique across all parentRef entries in the Route.
* They do not select different objects, but for each optional field used,
each ParentRef that selects the same object must set the same set of
optional fields to different values. If one ParentRef sets a
combination of optional fields, all must set the same combination.
Some examples:
* If one ParentRef sets `sectionName`, all ParentRefs referencing the
same object must also set `sectionName`.
* If one ParentRef sets `port`, all ParentRefs referencing the same
object must also set `port`.
* If one ParentRef sets `sectionName` and `port`, all ParentRefs
referencing the same object must also set `sectionName` and `port`.
It is possible to separately reference multiple distinct objects that may
be collapsed by an implementation. For example, some implementations may
choose to merge compatible Gateway Listeners together. If that is the
case, the list of routes attached to those resources should also be
merged.
Note that for ParentRefs that cross namespace boundaries, there are specific
rules. Cross-namespace references are only valid if they are explicitly
allowed by something in the namespace they are referring to. For example,
Gateway has the AllowedRoutes field, and ReferenceGrant provides a
generic way to enable other kinds of cross-namespace reference.

ParentRefs from a Route to a Service in the same namespace are "producer"
routes, which apply default routing rules to inbound connections from
any namespace to the Service.
ParentRefs from a Route to a Service in a different namespace are
"consumer" routes, and these routing rules are only applied to outbound
connections originating from the same namespace as the Route, for which
the intended destination of the connections are a Service targeted as a
ParentRef of the Route.




| | MaxItems: 32
| +| `hostnames` _[Hostname](#hostname) array_ | Hostnames defines a set of hostnames to match against the GRPC
Host header to select a GRPCRoute to process the request. This matches
the RFC 1123 definition of a hostname with 2 notable exceptions:
1. IPs are not allowed.
2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard
label MUST appear by itself as the first label.
If a hostname is specified by both the Listener and GRPCRoute, there
MUST be at least one intersecting hostname for the GRPCRoute to be
attached to the Listener. For example:
* A Listener with `test.example.com` as the hostname matches GRPCRoutes
that have either not specified any hostnames, or have specified at
least one of `test.example.com` or `*.example.com`.
* A Listener with `*.example.com` as the hostname matches GRPCRoutes
that have either not specified any hostnames or have specified at least
one hostname that matches the Listener hostname. For example,
`test.example.com` and `*.example.com` would both match. On the other
hand, `example.com` and `test.example.net` would not match.
Hostnames that are prefixed with a wildcard label (`*.`) are interpreted
as a suffix match. That means that a match for `*.example.com` would match
both `test.example.com`, and `foo.test.example.com`, but not `example.com`.
If both the Listener and GRPCRoute have specified hostnames, any
GRPCRoute hostnames that do not match the Listener hostname MUST be
ignored. For example, if a Listener specified `*.example.com`, and the
GRPCRoute specified `test.example.com` and `test.example.net`,
`test.example.net` MUST NOT be considered for a match.
If both the Listener and GRPCRoute have specified hostnames, and none
match with the criteria above, then the GRPCRoute MUST NOT be accepted by
the implementation. The implementation MUST raise an 'Accepted' Condition
with a status of `False` in the corresponding RouteParentStatus.
If a Route (A) of type HTTPRoute or GRPCRoute is attached to a
Listener and that listener already has another Route (B) of the other
type attached and the intersection of the hostnames of A and B is
non-empty, then the implementation MUST accept exactly one of these two
routes, determined by the following criteria, in order:
* The oldest Route based on creation timestamp.
* The Route appearing first in alphabetical order by
"\{namespace\}/\{name\}".
The rejected Route MUST raise an 'Accepted' condition with a status of
'False' in the corresponding RouteParentStatus.
Support: Core | | MaxItems: 16
MaxLength: 253
MinLength: 1
Pattern: `^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `rules` _[GRPCRouteRule](#grpcrouterule) array_ | Rules are a list of GRPC matchers, filters and actions.
| | MaxItems: 16
| + + +#### GRPCRouteStatus + + + +GRPCRouteStatus defines the observed state of GRPCRoute. + + + +_Appears in:_ +- [GRPCRoute](#grpcroute) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `parents` _[RouteParentStatus](#routeparentstatus) array_ | Parents is a list of parent resources (usually Gateways) that are
associated with the route, and the status of the route with respect to
each parent. When this route attaches to a parent, the controller that
manages the parent must add an entry to this list when the controller
first sees the route and should update the entry as appropriate when the
route or gateway is modified.
Note that parent references that cannot be resolved by an implementation
of this API will not be added to this list. Implementations of this API
can only populate Route status for the Gateways/parent resources they are
responsible for.
A maximum of 32 Gateways will be represented in this list. An empty list
means the route has not been attached to any Gateway. | | MaxItems: 32
| + + +#### Gateway + + + +Gateway represents an instance of a service-traffic handling infrastructure +by binding Listeners to a set of IP addresses. + + + +_Appears in:_ +- [Gateway](#gateway) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1` | | | +| `kind` _string_ | `Gateway` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[GatewaySpec](#gatewayspec)_ | Spec defines the desired state of Gateway. | | | +| `status` _[GatewayStatus](#gatewaystatus)_ | Status defines the current state of Gateway. | \{ conditions:[map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted] map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Programmed]] \} | | + + +#### GatewayBackendTLS + + + +GatewayBackendTLS describes backend TLS configuration for gateway. + + + +_Appears in:_ +- [GatewaySpec](#gatewayspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `clientCertificateRef` _[SecretObjectReference](#secretobjectreference)_ | ClientCertificateRef is a reference to an object that contains a Client
Certificate and the associated private key.
References to a resource in different namespace are invalid UNLESS there
is a ReferenceGrant in the target namespace that allows the certificate
to be attached. If a ReferenceGrant does not allow this reference, the
"ResolvedRefs" condition MUST be set to False for this listener with the
"RefNotPermitted" reason.
ClientCertificateRef can reference to standard Kubernetes resources, i.e.
Secret, or implementation-specific custom resources.
This setting can be overridden on the service level by use of BackendTLSPolicy.
Support: Core
| | | + + +#### GatewayClass + + + +GatewayClass describes a class of Gateways available to the user for creating +Gateway resources. + +It is recommended that this resource be used as a template for Gateways. This +means that a Gateway is based on the state of the GatewayClass at the time it +was created and changes to the GatewayClass or associated parameters are not +propagated down to existing Gateways. This recommendation is intended to +limit the blast radius of changes to GatewayClass or associated parameters. +If implementations choose to propagate GatewayClass changes to existing +Gateways, that MUST be clearly documented by the implementation. + +Whenever one or more Gateways are using a GatewayClass, implementations SHOULD +add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the +associated GatewayClass. This ensures that a GatewayClass associated with a +Gateway is not deleted while in use. + +GatewayClass is a Cluster level resource. + + + +_Appears in:_ +- [GatewayClass](#gatewayclass) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1` | | | +| `kind` _string_ | `GatewayClass` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[GatewayClassSpec](#gatewayclassspec)_ | Spec defines the desired state of GatewayClass. | | | +| `status` _[GatewayClassStatus](#gatewayclassstatus)_ | Status defines the current state of GatewayClass.
Implementations MUST populate status on all GatewayClass resources which
specify their controller name. | \{ conditions:[map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted]] \} | | + + + + + + +#### GatewayClassSpec + + + +GatewayClassSpec reflects the configuration of a class of Gateways. + + + +_Appears in:_ +- [GatewayClass](#gatewayclass) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `controllerName` _[GatewayController](#gatewaycontroller)_ | ControllerName is the name of the controller that is managing Gateways of
this class. The value of this field MUST be a domain prefixed path.
Example: "example.net/gateway-controller".
This field is not mutable and cannot be empty.
Support: Core | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$`
| +| `parametersRef` _[ParametersReference](#parametersreference)_ | ParametersRef is a reference to a resource that contains the configuration
parameters corresponding to the GatewayClass. This is optional if the
controller does not require any additional configuration.
ParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap,
or an implementation-specific custom resource. The resource can be
cluster-scoped or namespace-scoped.
If the referent cannot be found, refers to an unsupported kind, or when
the data within that resource is malformed, the GatewayClass SHOULD be
rejected with the "Accepted" status condition set to "False" and an
"InvalidParameters" reason.
A Gateway for this GatewayClass may provide its own `parametersRef`. When both are specified,
the merging behavior is implementation specific.
It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway.
Support: Implementation-specific | | | +| `description` _string_ | Description helps describe a GatewayClass with more details. | | MaxLength: 64
| + + +#### GatewayClassStatus + + + +GatewayClassStatus is the current status for the GatewayClass. + + + +_Appears in:_ +- [GatewayClass](#gatewayclass) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#condition-v1-meta) array_ | Conditions is the current status from the controller for
this GatewayClass.
Controllers should prefer to publish conditions using values
of GatewayClassConditionType for the type of each Condition. | [map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted]] | MaxItems: 8
| +| `supportedFeatures` _[SupportedFeature](#supportedfeature) array_ | SupportedFeatures is the set of features the GatewayClass support.
It MUST be sorted in ascending alphabetical order by the Name key.
| | MaxItems: 64
| + + + + + + +#### GatewayController + +_Underlying type:_ _string_ + +GatewayController is the name of a Gateway API controller. It must be a +domain prefixed path. + +Valid values include: + +* "example.com/bar" + +Invalid values include: + +* "example.com" - must include path +* "foo.example.com" - must include path + +_Validation:_ +- MaxLength: 253 +- MinLength: 1 +- Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` + +_Appears in:_ +- [GatewayClassSpec](#gatewayclassspec) +- [RouteParentStatus](#routeparentstatus) + + + +#### GatewayInfrastructure + + + +GatewayInfrastructure defines infrastructure level attributes about a Gateway instance. + + + +_Appears in:_ +- [GatewaySpec](#gatewayspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `labels` _object (keys:[LabelKey](#labelkey), values:[LabelValue](#labelvalue))_ | Labels that SHOULD be applied to any resources created in response to this Gateway.
For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources.
For other implementations, this refers to any relevant (implementation specific) "labels" concepts.
An implementation may chose to add additional implementation-specific labels as they see fit.
If an implementation maps these labels to Pods, or any other resource that would need to be recreated when labels
change, it SHOULD clearly warn about this behavior in documentation.
Support: Extended | | MaxProperties: 8
| +| `annotations` _object (keys:[AnnotationKey](#annotationkey), values:[AnnotationValue](#annotationvalue))_ | Annotations that SHOULD be applied to any resources created in response to this Gateway.
For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources.
For other implementations, this refers to any relevant (implementation specific) "annotations" concepts.
An implementation may chose to add additional implementation-specific annotations as they see fit.
Support: Extended | | MaxProperties: 8
| +| `parametersRef` _[LocalParametersReference](#localparametersreference)_ | ParametersRef is a reference to a resource that contains the configuration
parameters corresponding to the Gateway. This is optional if the
controller does not require any additional configuration.
This follows the same semantics as GatewayClass's `parametersRef`, but on a per-Gateway basis
The Gateway's GatewayClass may provide its own `parametersRef`. When both are specified,
the merging behavior is implementation specific.
It is generally recommended that GatewayClass provides defaults that can be overridden by a Gateway.
If the referent cannot be found, refers to an unsupported kind, or when
the data within that resource is malformed, the Gateway SHOULD be
rejected with the "Accepted" status condition set to "False" and an
"InvalidParameters" reason.
Support: Implementation-specific | | | + + +#### GatewaySpec + + + +GatewaySpec defines the desired state of Gateway. + +Not all possible combinations of options specified in the Spec are +valid. Some invalid configurations can be caught synchronously via CRD +validation, but there are many cases that will require asynchronous +signaling via the GatewayStatus block. + + + +_Appears in:_ +- [Gateway](#gateway) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `gatewayClassName` _[ObjectName](#objectname)_ | GatewayClassName used for this Gateway. This is the name of a
GatewayClass resource. | | MaxLength: 253
MinLength: 1
| +| `listeners` _[Listener](#listener) array_ | Listeners associated with this Gateway. Listeners define
logical endpoints that are bound on this Gateway's addresses.
At least one Listener MUST be specified.
## Distinct Listeners
Each Listener in a set of Listeners (for example, in a single Gateway)
MUST be _distinct_, in that a traffic flow MUST be able to be assigned to
exactly one listener. (This section uses "set of Listeners" rather than
"Listeners in a single Gateway" because implementations MAY merge configuration
from multiple Gateways onto a single data plane, and these rules _also_
apply in that case).
Practically, this means that each listener in a set MUST have a unique
combination of Port, Protocol, and, if supported by the protocol, Hostname.
Some combinations of port, protocol, and TLS settings are considered
Core support and MUST be supported by implementations based on the objects
they support:
HTTPRoute
1. HTTPRoute, Port: 80, Protocol: HTTP
2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided
TLSRoute
1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough
"Distinct" Listeners have the following property:
**The implementation can match inbound requests to a single distinct
Listener**.
When multiple Listeners share values for fields (for
example, two Listeners with the same Port value), the implementation
can match requests to only one of the Listeners using other
Listener fields.
When multiple listeners have the same value for the Protocol field, then
each of the Listeners with matching Protocol values MUST have different
values for other fields.
The set of fields that MUST be different for a Listener differs per protocol.
The following rules define the rules for what fields MUST be considered for
Listeners to be distinct with each protocol currently defined in the
Gateway API spec.
The set of listeners that all share a protocol value MUST have _different_
values for _at least one_ of these fields to be distinct:
* **HTTP, HTTPS, TLS**: Port, Hostname
* **TCP, UDP**: Port
One **very** important rule to call out involves what happens when an
implementation:
* Supports TCP protocol Listeners, as well as HTTP, HTTPS, or TLS protocol
Listeners, and
* sees HTTP, HTTPS, or TLS protocols with the same `port` as one with TCP
Protocol.
In this case all the Listeners that share a port with the
TCP Listener are not distinct and so MUST NOT be accepted.
If an implementation does not support TCP Protocol Listeners, then the
previous rule does not apply, and the TCP Listeners SHOULD NOT be
accepted.
Note that the `tls` field is not used for determining if a listener is distinct, because
Listeners that _only_ differ on TLS config will still conflict in all cases.
### Listeners that are distinct only by Hostname
When the Listeners are distinct based only on Hostname, inbound request
hostnames MUST match from the most specific to least specific Hostname
values to choose the correct Listener and its associated set of Routes.
Exact matches MUST be processed before wildcard matches, and wildcard
matches MUST be processed before fallback (empty Hostname value)
matches. For example, `"foo.example.com"` takes precedence over
`"*.example.com"`, and `"*.example.com"` takes precedence over `""`.
Additionally, if there are multiple wildcard entries, more specific
wildcard entries must be processed before less specific wildcard entries.
For example, `"*.foo.example.com"` takes precedence over `"*.example.com"`.
The precise definition here is that the higher the number of dots in the
hostname to the right of the wildcard character, the higher the precedence.
The wildcard character will match any number of characters _and dots_ to
the left, however, so `"*.example.com"` will match both
`"foo.bar.example.com"` _and_ `"bar.example.com"`.
## Handling indistinct Listeners
If a set of Listeners contains Listeners that are not distinct, then those
Listeners are _Conflicted_, and the implementation MUST set the "Conflicted"
condition in the Listener Status to "True".
The words "indistinct" and "conflicted" are considered equivalent for the
purpose of this documentation.
Implementations MAY choose to accept a Gateway with some Conflicted
Listeners only if they only accept the partial Listener set that contains
no Conflicted Listeners.
Specifically, an implementation MAY accept a partial Listener set subject to
the following rules:
* The implementation MUST NOT pick one conflicting Listener as the winner.
ALL indistinct Listeners must not be accepted for processing.
* At least one distinct Listener MUST be present, or else the Gateway effectively
contains _no_ Listeners, and must be rejected from processing as a whole.
The implementation MUST set a "ListenersNotValid" condition on the
Gateway Status when the Gateway contains Conflicted Listeners whether or
not they accept the Gateway. That Condition SHOULD clearly
indicate in the Message which Listeners are conflicted, and which are
Accepted. Additionally, the Listener status for those listeners SHOULD
indicate which Listeners are conflicted and not Accepted.
## General Listener behavior
Note that, for all distinct Listeners, requests SHOULD match at most one Listener.
For example, if Listeners are defined for "foo.example.com" and "*.example.com", a
request to "foo.example.com" SHOULD only be routed using routes attached
to the "foo.example.com" Listener (and not the "*.example.com" Listener).
This concept is known as "Listener Isolation", and it is an Extended feature
of Gateway API. Implementations that do not support Listener Isolation MUST
clearly document this, and MUST NOT claim support for the
`GatewayHTTPListenerIsolation` feature.
Implementations that _do_ support Listener Isolation SHOULD claim support
for the Extended `GatewayHTTPListenerIsolation` feature and pass the associated
conformance tests.
## Compatible Listeners
A Gateway's Listeners are considered _compatible_ if:
1. They are distinct.
2. The implementation can serve them in compliance with the Addresses
requirement that all Listeners are available on all assigned
addresses.
Compatible combinations in Extended support are expected to vary across
implementations. A combination that is compatible for one implementation
may not be compatible for another.
For example, an implementation that cannot serve both TCP and UDP listeners
on the same address, or cannot mix HTTPS and generic TLS listens on the same port
would not consider those cases compatible, even though they are distinct.
Implementations MAY merge separate Gateways onto a single set of
Addresses if all Listeners across all Gateways are compatible.
In a future release the MinItems=1 requirement MAY be dropped.
Support: Core | | MaxItems: 64
MinItems: 1
| +| `addresses` _[GatewaySpecAddress](#gatewayspecaddress) array_ | Addresses requested for this Gateway. This is optional and behavior can
depend on the implementation. If a value is set in the spec and the
requested address is invalid or unavailable, the implementation MUST
indicate this in the associated entry in GatewayStatus.Addresses.
The Addresses field represents a request for the address(es) on the
"outside of the Gateway", that traffic bound for this Gateway will use.
This could be the IP address or hostname of an external load balancer or
other networking infrastructure, or some other address that traffic will
be sent to.
If no Addresses are specified, the implementation MAY schedule the
Gateway in an implementation-specific manner, assigning an appropriate
set of Addresses.
The implementation MUST bind all Listeners to every GatewayAddress that
it assigns to the Gateway and add a corresponding entry in
GatewayStatus.Addresses.
Support: Extended
| | MaxItems: 16
| +| `infrastructure` _[GatewayInfrastructure](#gatewayinfrastructure)_ | Infrastructure defines infrastructure level attributes about this Gateway instance.
Support: Extended | | | +| `backendTLS` _[GatewayBackendTLS](#gatewaybackendtls)_ | BackendTLS configures TLS settings for when this Gateway is connecting to
backends with TLS.
Support: Core
| | | +| `allowedListeners` _[AllowedListeners](#allowedlisteners)_ | AllowedListeners defines which ListenerSets can be attached to this Gateway.
While this feature is experimental, the default value is to allow no ListenerSets.
| | | + + +#### GatewaySpecAddress + + + +GatewaySpecAddress describes an address that can be bound to a Gateway. + + + +_Appears in:_ +- [GatewaySpec](#gatewayspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[AddressType](#addresstype)_ | Type of the address. | IPAddress | MaxLength: 253
MinLength: 1
Pattern: `^Hostname\|IPAddress\|NamedAddress\|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$`
| +| `value` _string_ | When a value is unspecified, an implementation SHOULD automatically
assign an address matching the requested type if possible.
If an implementation does not support an empty value, they MUST set the
"Programmed" condition in status to False with a reason of "AddressNotAssigned".
Examples: `1.2.3.4`, `128::1`, `my-ip-address`. | | MaxLength: 253
| + + +#### GatewayStatus + + + +GatewayStatus defines the observed state of Gateway. + + + +_Appears in:_ +- [Gateway](#gateway) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `addresses` _[GatewayStatusAddress](#gatewaystatusaddress) array_ | Addresses lists the network addresses that have been bound to the
Gateway.
This list may differ from the addresses provided in the spec under some
conditions:
* no addresses are specified, all addresses are dynamically assigned
* a combination of specified and dynamic addresses are assigned
* a specified address was unusable (e.g. already in use)
| | MaxItems: 16
| +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#condition-v1-meta) array_ | Conditions describe the current conditions of the Gateway.
Implementations should prefer to express Gateway conditions
using the `GatewayConditionType` and `GatewayConditionReason`
constants so that operators and tools can converge on a common
vocabulary to describe Gateway state.
Known condition types are:
* "Accepted"
* "Programmed"
* "Ready" | [map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted] map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Programmed]] | MaxItems: 8
| +| `listeners` _[ListenerStatus](#listenerstatus) array_ | Listeners provide status for each unique listener port defined in the Spec. | | MaxItems: 64
| + + +#### GatewayStatusAddress + + + +GatewayStatusAddress describes a network address that is bound to a Gateway. + + + +_Appears in:_ +- [GatewayStatus](#gatewaystatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[AddressType](#addresstype)_ | Type of the address. | IPAddress | MaxLength: 253
MinLength: 1
Pattern: `^Hostname\|IPAddress\|NamedAddress\|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$`
| +| `value` _string_ | Value of the address. The validity of the values will depend
on the type and support by the controller.
Examples: `1.2.3.4`, `128::1`, `my-ip-address`. | | MaxLength: 253
MinLength: 1
| + + +#### GatewayTLSConfig + + + +GatewayTLSConfig describes a TLS configuration. + + + +_Appears in:_ +- [Listener](#listener) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `mode` _[TLSModeType](#tlsmodetype)_ | Mode defines the TLS behavior for the TLS session initiated by the client.
There are two possible modes:
- Terminate: The TLS session between the downstream client and the
Gateway is terminated at the Gateway. This mode requires certificates
to be specified in some way, such as populating the certificateRefs
field.
- Passthrough: The TLS session is NOT terminated by the Gateway. This
implies that the Gateway can't decipher the TLS stream except for
the ClientHello message of the TLS protocol. The certificateRefs field
is ignored in this mode.
Support: Core | Terminate | Enum: [Terminate Passthrough]
| +| `certificateRefs` _[SecretObjectReference](#secretobjectreference) array_ | CertificateRefs contains a series of references to Kubernetes objects that
contains TLS certificates and private keys. These certificates are used to
establish a TLS handshake for requests that match the hostname of the
associated listener.
A single CertificateRef to a Kubernetes Secret has "Core" support.
Implementations MAY choose to support attaching multiple certificates to
a Listener, but this behavior is implementation-specific.
References to a resource in different namespace are invalid UNLESS there
is a ReferenceGrant in the target namespace that allows the certificate
to be attached. If a ReferenceGrant does not allow this reference, the
"ResolvedRefs" condition MUST be set to False for this listener with the
"RefNotPermitted" reason.
This field is required to have at least one element when the mode is set
to "Terminate" (default) and is optional otherwise.
CertificateRefs can reference to standard Kubernetes resources, i.e.
Secret, or implementation-specific custom resources.
Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls
Support: Implementation-specific (More than one reference or other resource types) | | MaxItems: 64
| +| `frontendValidation` _[FrontendTLSValidation](#frontendtlsvalidation)_ | FrontendValidation holds configuration information for validating the frontend (client).
Setting this field will require clients to send a client certificate
required for validation during the TLS handshake. In browsers this may result in a dialog appearing
that requests a user to specify the client certificate.
The maximum depth of a certificate chain accepted in verification is Implementation specific.
Support: Extended
| | | +| `options` _object (keys:[AnnotationKey](#annotationkey), values:[AnnotationValue](#annotationvalue))_ | Options are a list of key/value pairs to enable extended TLS
configuration for each implementation. For example, configuring the
minimum TLS version or supported cipher suites.
A set of common keys MAY be defined by the API in the future. To avoid
any ambiguity, implementation-specific definitions MUST use
domain-prefixed names, such as `example.com/my-custom-option`.
Un-prefixed names are reserved for key names defined by Gateway API.
Support: Implementation-specific | | MaxProperties: 16
| + + +#### Group + +_Underlying type:_ _string_ + +Group refers to a Kubernetes Group. It must either be an empty string or a +RFC 1123 subdomain. + +This validation is based off of the corresponding Kubernetes validation: +https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 + +Valid values include: + +* "" - empty string implies core Kubernetes API group +* "gateway.networking.k8s.io" +* "foo.example.com" + +Invalid values include: + +* "example.com/bar" - "/" is an invalid character + +_Validation:_ +- MaxLength: 253 +- Pattern: `^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` + +_Appears in:_ +- [BackendObjectReference](#backendobjectreference) +- [BackendRef](#backendref) +- [GRPCBackendRef](#grpcbackendref) +- [HTTPBackendRef](#httpbackendref) +- [LocalObjectReference](#localobjectreference) +- [LocalParametersReference](#localparametersreference) +- [ObjectReference](#objectreference) +- [ParametersReference](#parametersreference) +- [ParentReference](#parentreference) +- [RouteGroupKind](#routegroupkind) +- [SecretObjectReference](#secretobjectreference) + + + +#### HTTPBackendRef + + + +HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. + +Note that when a namespace different than the local namespace is specified, a +ReferenceGrant object is required in the referent namespace to allow that +namespace's owner to accept the reference. See the ReferenceGrant +documentation for details. + + + +When the BackendRef points to a Kubernetes Service, implementations SHOULD +honor the appProtocol field if it is set for the target Service Port. + +Implementations supporting appProtocol SHOULD recognize the Kubernetes +Standard Application Protocols defined in KEP-3726. + +If a Service appProtocol isn't specified, an implementation MAY infer the +backend protocol through its own means. Implementations MAY infer the +protocol from the Route type referring to the backend Service. + +If a Route is not able to send traffic to the backend using the specified +protocol then the backend is considered invalid. Implementations MUST set the +"ResolvedRefs" condition to "False" with the "UnsupportedProtocol" reason. + + + + + +_Appears in:_ +- [HTTPRouteRule](#httprouterule) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent. For example, "gateway.networking.k8s.io".
When unspecified or empty string, core API group is inferred. | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is the Kubernetes resource kind of the referent. For example
"Service".
Defaults to "Service" when not specified.
ExternalName services can refer to CNAME DNS records that may live
outside of the cluster and as such are difficult to reason about in
terms of conformance. They also may not be safe to forward to (see
CVE-2021-25740 for more information). Implementations SHOULD NOT
support ExternalName Services.
Support: Core (Services with a type other than ExternalName)
Support: Implementation-specific (Services with type ExternalName) | Service | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. | | MaxLength: 253
MinLength: 1
| +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the backend. When unspecified, the local
namespace is inferred.
Note that when a namespace different than the local namespace is specified,
a ReferenceGrant object is required in the referent namespace to allow that
namespace's owner to accept the reference. See the ReferenceGrant
documentation for details.
Support: Core | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| +| `port` _[PortNumber](#portnumber)_ | Port specifies the destination port number to use for this resource.
Port is required when the referent is a Kubernetes Service. In this
case, the port number is the service port number, not the target port.
For other resources, destination port might be derived from the referent
resource or this field. | | Maximum: 65535
Minimum: 1
| +| `weight` _integer_ | Weight specifies the proportion of requests forwarded to the referenced
backend. This is computed as weight/(sum of all weights in this
BackendRefs list). For non-zero values, there may be some epsilon from
the exact proportion defined here depending on the precision an
implementation supports. Weight is not a percentage and the sum of
weights does not need to equal 100.
If only one backend is specified and it has a weight greater than 0, 100%
of the traffic is forwarded to that backend. If weight is set to 0, no
traffic should be forwarded for this entry. If unspecified, weight
defaults to 1.
Support for this field varies based on the context where used. | 1 | Maximum: 1e+06
Minimum: 0
| +| `filters` _[HTTPRouteFilter](#httproutefilter) array_ | Filters defined at this level should be executed if and only if the
request is being forwarded to the backend defined here.
Support: Implementation-specific (For broader support of filters, use the
Filters field in HTTPRouteRule.) | | MaxItems: 16
| + + +#### HTTPCORSFilter + + + +HTTPCORSFilter defines a filter that that configures Cross-Origin Request +Sharing (CORS). + + + +_Appears in:_ +- [HTTPRouteFilter](#httproutefilter) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `allowOrigins` _[AbsoluteURI](#absoluteuri) array_ | AllowOrigins indicates whether the response can be shared with requested
resource from the given `Origin`.
The `Origin` consists of a scheme and a host, with an optional port, and
takes the form `://(:)`.
Valid values for scheme are: `http` and `https`.
Valid values for port are any integer between 1 and 65535 (the list of
available TCP/UDP ports). Note that, if not included, port `80` is
assumed for `http` scheme origins, and port `443` is assumed for `https`
origins. This may affect origin matching.
The host part of the origin may contain the wildcard character `*`. These
wildcard characters behave as follows:
* `*` is a greedy match to the _left_, including any number of
DNS labels to the left of its position. This also means that
`*` will include any number of period `.` characters to the
left of its position.
* A wildcard by itself matches all hosts.
An origin value that includes _only_ the `*` character indicates requests
from all `Origin`s are allowed.
When the `AllowOrigins` field is configured with multiple origins, it
means the server supports clients from multiple origins. If the request
`Origin` matches the configured allowed origins, the gateway must return
the given `Origin` and sets value of the header
`Access-Control-Allow-Origin` same as the `Origin` header provided by the
client.
The status code of a successful response to a "preflight" request is
always an OK status (i.e., 204 or 200).
If the request `Origin` does not match the configured allowed origins,
the gateway returns 204/200 response but doesn't set the relevant
cross-origin response headers. Alternatively, the gateway responds with
403 status to the "preflight" request is denied, coupled with omitting
the CORS headers. The cross-origin request fails on the client side.
Therefore, the client doesn't attempt the actual cross-origin request.
The `Access-Control-Allow-Origin` response header can only use `*`
wildcard as value when the `AllowCredentials` field is unspecified.
When the `AllowCredentials` field is specified and `AllowOrigins` field
specified with the `*` wildcard, the gateway must return a single origin
in the value of the `Access-Control-Allow-Origin` response header,
instead of specifying the `*` wildcard. The value of the header
`Access-Control-Allow-Origin` is same as the `Origin` header provided by
the client.
Support: Extended | | MaxItems: 64
MaxLength: 253
MinLength: 1
Pattern: `^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?`
| +| `allowCredentials` _[TrueField](#truefield)_ | AllowCredentials indicates whether the actual cross-origin request allows
to include credentials.
The only valid value for the `Access-Control-Allow-Credentials` response
header is true (case-sensitive).
If the credentials are not allowed in cross-origin requests, the gateway
will omit the header `Access-Control-Allow-Credentials` entirely rather
than setting its value to false.
Support: Extended | | Enum: [true]
| +| `allowMethods` _[HTTPMethodWithWildcard](#httpmethodwithwildcard) array_ | AllowMethods indicates which HTTP methods are supported for accessing the
requested resource.
Valid values are any method defined by RFC9110, along with the special
value `*`, which represents all HTTP methods are allowed.
Method names are case sensitive, so these values are also case-sensitive.
(See https://www.rfc-editor.org/rfc/rfc2616#section-5.1.1)
Multiple method names in the value of the `Access-Control-Allow-Methods`
response header are separated by a comma (",").
A CORS-safelisted method is a method that is `GET`, `HEAD`, or `POST`.
(See https://fetch.spec.whatwg.org/#cors-safelisted-method) The
CORS-safelisted methods are always allowed, regardless of whether they
are specified in the `AllowMethods` field.
When the `AllowMethods` field is configured with one or more methods, the
gateway must return the `Access-Control-Allow-Methods` response header
which value is present in the `AllowMethods` field.
If the HTTP method of the `Access-Control-Request-Method` request header
is not included in the list of methods specified by the response header
`Access-Control-Allow-Methods`, it will present an error on the client
side.
The `Access-Control-Allow-Methods` response header can only use `*`
wildcard as value when the `AllowCredentials` field is unspecified.
When the `AllowCredentials` field is specified and `AllowMethods` field
specified with the `*` wildcard, the gateway must specify one HTTP method
in the value of the Access-Control-Allow-Methods response header. The
value of the header `Access-Control-Allow-Methods` is same as the
`Access-Control-Request-Method` header provided by the client. If the
header `Access-Control-Request-Method` is not included in the request,
the gateway will omit the `Access-Control-Allow-Methods` response header,
instead of specifying the `*` wildcard. A Gateway implementation may
choose to add implementation-specific default methods.
Support: Extended | | Enum: [GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATCH *]
MaxItems: 9
| +| `allowHeaders` _[HTTPHeaderName](#httpheadername) array_ | AllowHeaders indicates which HTTP request headers are supported for
accessing the requested resource.
Header names are not case sensitive.
Multiple header names in the value of the `Access-Control-Allow-Headers`
response header are separated by a comma (",").
When the `AllowHeaders` field is configured with one or more headers, the
gateway must return the `Access-Control-Allow-Headers` response header
which value is present in the `AllowHeaders` field.
If any header name in the `Access-Control-Request-Headers` request header
is not included in the list of header names specified by the response
header `Access-Control-Allow-Headers`, it will present an error on the
client side.
If any header name in the `Access-Control-Allow-Headers` response header
does not recognize by the client, it will also occur an error on the
client side.
A wildcard indicates that the requests with all HTTP headers are allowed.
The `Access-Control-Allow-Headers` response header can only use `*`
wildcard as value when the `AllowCredentials` field is unspecified.
When the `AllowCredentials` field is specified and `AllowHeaders` field
specified with the `*` wildcard, the gateway must specify one or more
HTTP headers in the value of the `Access-Control-Allow-Headers` response
header. The value of the header `Access-Control-Allow-Headers` is same as
the `Access-Control-Request-Headers` header provided by the client. If
the header `Access-Control-Request-Headers` is not included in the
request, the gateway will omit the `Access-Control-Allow-Headers`
response header, instead of specifying the `*` wildcard. A Gateway
implementation may choose to add implementation-specific default headers.
Support: Extended | | MaxItems: 64
MaxLength: 256
MinLength: 1
Pattern: `^[A-Za-z0-9!#$%&'*+\-.^_\x60\|~]+$`
| +| `exposeHeaders` _[HTTPHeaderName](#httpheadername) array_ | ExposeHeaders indicates which HTTP response headers can be exposed
to client-side scripts in response to a cross-origin request.
A CORS-safelisted response header is an HTTP header in a CORS response
that it is considered safe to expose to the client scripts.
The CORS-safelisted response headers include the following headers:
`Cache-Control`
`Content-Language`
`Content-Length`
`Content-Type`
`Expires`
`Last-Modified`
`Pragma`
(See https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name)
The CORS-safelisted response headers are exposed to client by default.
When an HTTP header name is specified using the `ExposeHeaders` field,
this additional header will be exposed as part of the response to the
client.
Header names are not case sensitive.
Multiple header names in the value of the `Access-Control-Expose-Headers`
response header are separated by a comma (",").
A wildcard indicates that the responses with all HTTP headers are exposed
to clients. The `Access-Control-Expose-Headers` response header can only
use `*` wildcard as value when the `AllowCredentials` field is
unspecified.
Support: Extended | | MaxItems: 64
MaxLength: 256
MinLength: 1
Pattern: `^[A-Za-z0-9!#$%&'*+\-.^_\x60\|~]+$`
| +| `maxAge` _integer_ | MaxAge indicates the duration (in seconds) for the client to cache the
results of a "preflight" request.
The information provided by the `Access-Control-Allow-Methods` and
`Access-Control-Allow-Headers` response headers can be cached by the
client until the time specified by `Access-Control-Max-Age` elapses.
The default value of `Access-Control-Max-Age` response header is 5
(seconds). | 5 | Minimum: 1
| + + +#### HTTPHeader + + + +HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + + + +_Appears in:_ +- [HTTPHeaderFilter](#httpheaderfilter) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _[HTTPHeaderName](#httpheadername)_ | Name is the name of the HTTP Header to be matched. Name matching MUST be
case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
If multiple entries specify equivalent header names, the first entry with
an equivalent name MUST be considered for a match. Subsequent entries
with an equivalent header name MUST be ignored. Due to the
case-insensitivity of header names, "foo" and "Foo" are considered
equivalent. | | MaxLength: 256
MinLength: 1
Pattern: `^[A-Za-z0-9!#$%&'*+\-.^_\x60\|~]+$`
| +| `value` _string_ | Value is the value of HTTP Header to be matched. | | MaxLength: 4096
MinLength: 1
| + + +#### HTTPHeaderFilter + + + +HTTPHeaderFilter defines a filter that modifies the headers of an HTTP +request or response. Only one action for a given header name is permitted. +Filters specifying multiple actions of the same or different type for any one +header name are invalid and will be rejected by CRD validation. +Configuration to set or add multiple values for a header must use RFC 7230 +header value formatting, separating each value with a comma. + + + +_Appears in:_ +- [GRPCRouteFilter](#grpcroutefilter) +- [HTTPRouteFilter](#httproutefilter) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `set` _[HTTPHeader](#httpheader) array_ | Set overwrites the request with the given header (name, value)
before the action.
Input:
GET /foo HTTP/1.1
my-header: foo
Config:
set:
- name: "my-header"
value: "bar"
Output:
GET /foo HTTP/1.1
my-header: bar | | MaxItems: 16
| +| `add` _[HTTPHeader](#httpheader) array_ | Add adds the given header(s) (name, value) to the request
before the action. It appends to any existing values associated
with the header name.
Input:
GET /foo HTTP/1.1
my-header: foo
Config:
add:
- name: "my-header"
value: "bar,baz"
Output:
GET /foo HTTP/1.1
my-header: foo,bar,baz | | MaxItems: 16
| +| `remove` _string array_ | Remove the given header(s) from the HTTP request before the action. The
value of Remove is a list of HTTP header names. Note that the header
names are case-insensitive (see
https://datatracker.ietf.org/doc/html/rfc2616#section-4.2).
Input:
GET /foo HTTP/1.1
my-header1: foo
my-header2: bar
my-header3: baz
Config:
remove: ["my-header1", "my-header3"]
Output:
GET /foo HTTP/1.1
my-header2: bar | | MaxItems: 16
| + + +#### HTTPHeaderMatch + + + +HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request +headers. + + + +_Appears in:_ +- [HTTPRouteMatch](#httproutematch) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[HeaderMatchType](#headermatchtype)_ | Type specifies how to match against the value of the header.
Support: Core (Exact)
Support: Implementation-specific (RegularExpression)
Since RegularExpression HeaderMatchType has implementation-specific
conformance, implementations can support POSIX, PCRE or any other dialects
of regular expressions. Please read the implementation's documentation to
determine the supported dialect. | Exact | Enum: [Exact RegularExpression]
| +| `name` _[HTTPHeaderName](#httpheadername)_ | Name is the name of the HTTP Header to be matched. Name matching MUST be
case-insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2).
If multiple entries specify equivalent header names, only the first
entry with an equivalent name MUST be considered for a match. Subsequent
entries with an equivalent header name MUST be ignored. Due to the
case-insensitivity of header names, "foo" and "Foo" are considered
equivalent.
When a header is repeated in an HTTP request, it is
implementation-specific behavior as to how this is represented.
Generally, proxies should follow the guidance from the RFC:
https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding
processing a repeated header, with special handling for "Set-Cookie". | | MaxLength: 256
MinLength: 1
Pattern: `^[A-Za-z0-9!#$%&'*+\-.^_\x60\|~]+$`
| +| `value` _string_ | Value is the value of HTTP Header to be matched. | | MaxLength: 4096
MinLength: 1
| + + +#### HTTPHeaderName + +_Underlying type:_ _[HeaderName](#headername)_ + +HTTPHeaderName is the name of an HTTP header. + +Valid values include: + +* "Authorization" +* "Set-Cookie" + +Invalid values include: + + - ":method" - ":" is an invalid character. This means that HTTP/2 pseudo + headers are not currently supported by this type. + - "/invalid" - "/ " is an invalid character + +_Validation:_ +- MaxLength: 256 +- MinLength: 1 +- Pattern: `^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$` + +_Appears in:_ +- [HTTPCORSFilter](#httpcorsfilter) +- [HTTPHeader](#httpheader) +- [HTTPHeaderMatch](#httpheadermatch) +- [HTTPQueryParamMatch](#httpqueryparammatch) + + + +#### HTTPMethod + +_Underlying type:_ _string_ + +HTTPMethod describes how to select a HTTP route by matching the HTTP +method as defined by +[RFC 7231](https://datatracker.ietf.org/doc/html/rfc7231#section-4) and +[RFC 5789](https://datatracker.ietf.org/doc/html/rfc5789#section-2). +The value is expected in upper case. + +Note that values may be added to this enum, implementations +must ensure that unknown values will not cause a crash. + +Unknown values here must result in the implementation setting the +Accepted Condition for the Route to `status: False`, with a +Reason of `UnsupportedValue`. + +_Validation:_ +- Enum: [GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATCH] + +_Appears in:_ +- [HTTPRouteMatch](#httproutematch) + +| Field | Description | +| --- | --- | +| `GET` | | +| `HEAD` | | +| `POST` | | +| `PUT` | | +| `DELETE` | | +| `CONNECT` | | +| `OPTIONS` | | +| `TRACE` | | +| `PATCH` | | + + +#### HTTPMethodWithWildcard + +_Underlying type:_ _string_ + + + +_Validation:_ +- Enum: [GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATCH *] + +_Appears in:_ +- [HTTPCORSFilter](#httpcorsfilter) + + + +#### HTTPPathMatch + + + +HTTPPathMatch describes how to select a HTTP route by matching the HTTP request path. + + + +_Appears in:_ +- [HTTPRouteMatch](#httproutematch) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[PathMatchType](#pathmatchtype)_ | Type specifies how to match against the path Value.
Support: Core (Exact, PathPrefix)
Support: Implementation-specific (RegularExpression) | PathPrefix | Enum: [Exact PathPrefix RegularExpression]
| +| `value` _string_ | Value of the HTTP path to match against. | / | MaxLength: 1024
| + + +#### HTTPPathModifier + + + +HTTPPathModifier defines configuration for path modifiers. + + + +_Appears in:_ +- [HTTPRequestRedirectFilter](#httprequestredirectfilter) +- [HTTPURLRewriteFilter](#httpurlrewritefilter) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[HTTPPathModifierType](#httppathmodifiertype)_ | Type defines the type of path modifier. Additional types may be
added in a future release of the API.
Note that values may be added to this enum, implementations
must ensure that unknown values will not cause a crash.
Unknown values here must result in the implementation setting the
Accepted Condition for the Route to `status: False`, with a
Reason of `UnsupportedValue`. | | Enum: [ReplaceFullPath ReplacePrefixMatch]
| +| `replaceFullPath` _string_ | ReplaceFullPath specifies the value with which to replace the full path
of a request during a rewrite or redirect. | | MaxLength: 1024
| +| `replacePrefixMatch` _string_ | ReplacePrefixMatch specifies the value with which to replace the prefix
match of a request during a rewrite or redirect. For example, a request
to "/foo/bar" with a prefix match of "/foo" and a ReplacePrefixMatch
of "/xyz" would be modified to "/xyz/bar".
Note that this matches the behavior of the PathPrefix match type. This
matches full path elements. A path element refers to the list of labels
in the path split by the `/` separator. When specified, a trailing `/` is
ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all
match the prefix `/abc`, but the path `/abcd` would not.
ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch.
Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in
the implementation setting the Accepted Condition for the Route to `status: False`.
Request Path \| Prefix Match \| Replace Prefix \| Modified Path | | MaxLength: 1024
| + + +#### HTTPPathModifierType + +_Underlying type:_ _string_ + +HTTPPathModifierType defines the type of path redirect or rewrite. + + + +_Appears in:_ +- [HTTPPathModifier](#httppathmodifier) + +| Field | Description | +| --- | --- | +| `ReplaceFullPath` | This type of modifier indicates that the full path will be replaced
by the specified value.
| +| `ReplacePrefixMatch` | This type of modifier indicates that any prefix path matches will be
replaced by the substitution value. For example, a path with a prefix
match of "/foo" and a ReplacePrefixMatch substitution of "/bar" will have
the "/foo" prefix replaced with "/bar" in matching requests.
Note that this matches the behavior of the PathPrefix match type. This
matches full path elements. A path element refers to the list of labels
in the path split by the `/` separator. When specified, a trailing `/` is
ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all
match the prefix `/abc`, but the path `/abcd` would not.
| + + +#### HTTPQueryParamMatch + + + +HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP +query parameters. + + + +_Appears in:_ +- [HTTPRouteMatch](#httproutematch) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[QueryParamMatchType](#queryparammatchtype)_ | Type specifies how to match against the value of the query parameter.
Support: Extended (Exact)
Support: Implementation-specific (RegularExpression)
Since RegularExpression QueryParamMatchType has Implementation-specific
conformance, implementations can support POSIX, PCRE or any other
dialects of regular expressions. Please read the implementation's
documentation to determine the supported dialect. | Exact | Enum: [Exact RegularExpression]
| +| `name` _[HTTPHeaderName](#httpheadername)_ | Name is the name of the HTTP query param to be matched. This must be an
exact string match. (See
https://tools.ietf.org/html/rfc7230#section-2.7.3).
If multiple entries specify equivalent query param names, only the first
entry with an equivalent name MUST be considered for a match. Subsequent
entries with an equivalent query param name MUST be ignored.
If a query param is repeated in an HTTP request, the behavior is
purposely left undefined, since different data planes have different
capabilities. However, it is *recommended* that implementations should
match against the first value of the param if the data plane supports it,
as this behavior is expected in other load balancing contexts outside of
the Gateway API.
Users SHOULD NOT route traffic based on repeated query params to guard
themselves against potential differences in the implementations. | | MaxLength: 256
MinLength: 1
Pattern: `^[A-Za-z0-9!#$%&'*+\-.^_\x60\|~]+$`
| +| `value` _string_ | Value is the value of HTTP query param to be matched. | | MaxLength: 1024
MinLength: 1
| + + +#### HTTPRequestMirrorFilter + + + +HTTPRequestMirrorFilter defines configuration for the RequestMirror filter. + + + +_Appears in:_ +- [GRPCRouteFilter](#grpcroutefilter) +- [HTTPRouteFilter](#httproutefilter) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `backendRef` _[BackendObjectReference](#backendobjectreference)_ | BackendRef references a resource where mirrored requests are sent.
Mirrored requests must be sent only to a single destination endpoint
within this BackendRef, irrespective of how many endpoints are present
within this BackendRef.
If the referent cannot be found, this BackendRef is invalid and must be
dropped from the Gateway. The controller must ensure the "ResolvedRefs"
condition on the Route status is set to `status: False` and not configure
this backend in the underlying implementation.
If there is a cross-namespace reference to an *existing* object
that is not allowed by a ReferenceGrant, the controller must ensure the
"ResolvedRefs" condition on the Route is set to `status: False`,
with the "RefNotPermitted" reason and not configure this backend in the
underlying implementation.
In either error case, the Message of the `ResolvedRefs` Condition
should be used to provide more detail about the problem.
Support: Extended for Kubernetes Service
Support: Implementation-specific for any other resource | | | +| `percent` _integer_ | Percent represents the percentage of requests that should be
mirrored to BackendRef. Its minimum value is 0 (indicating 0% of
requests) and its maximum value is 100 (indicating 100% of requests).
Only one of Fraction or Percent may be specified. If neither field
is specified, 100% of requests will be mirrored. | | Maximum: 100
Minimum: 0
| +| `fraction` _[Fraction](#fraction)_ | Fraction represents the fraction of requests that should be
mirrored to BackendRef.
Only one of Fraction or Percent may be specified. If neither field
is specified, 100% of requests will be mirrored. | | | + + +#### HTTPRequestRedirectFilter + + + +HTTPRequestRedirect defines a filter that redirects a request. This filter +MUST NOT be used on the same Route rule as a HTTPURLRewrite filter. + + + +_Appears in:_ +- [HTTPRouteFilter](#httproutefilter) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `scheme` _string_ | Scheme is the scheme to be used in the value of the `Location` header in
the response. When empty, the scheme of the request is used.
Scheme redirects can affect the port of the redirect, for more information,
refer to the documentation for the port field of this filter.
Note that values may be added to this enum, implementations
must ensure that unknown values will not cause a crash.
Unknown values here must result in the implementation setting the
Accepted Condition for the Route to `status: False`, with a
Reason of `UnsupportedValue`.
Support: Extended | | Enum: [http https]
| +| `hostname` _[PreciseHostname](#precisehostname)_ | Hostname is the hostname to be used in the value of the `Location`
header in the response.
When empty, the hostname in the `Host` header of the request is used.
Support: Core | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `path` _[HTTPPathModifier](#httppathmodifier)_ | Path defines parameters used to modify the path of the incoming request.
The modified path is then used to construct the `Location` header. When
empty, the request path is used as-is.
Support: Extended | | | +| `port` _[PortNumber](#portnumber)_ | Port is the port to be used in the value of the `Location`
header in the response.
If no port is specified, the redirect port MUST be derived using the
following rules:
* If redirect scheme is not-empty, the redirect port MUST be the well-known
port associated with the redirect scheme. Specifically "http" to port 80
and "https" to port 443. If the redirect scheme does not have a
well-known port, the listener port of the Gateway SHOULD be used.
* If redirect scheme is empty, the redirect port MUST be the Gateway
Listener port.
Implementations SHOULD NOT add the port number in the 'Location'
header in the following cases:
* A Location header that will use HTTP (whether that is determined via
the Listener protocol or the Scheme field) _and_ use port 80.
* A Location header that will use HTTPS (whether that is determined via
the Listener protocol or the Scheme field) _and_ use port 443.
Support: Extended | | Maximum: 65535
Minimum: 1
| +| `statusCode` _integer_ | StatusCode is the HTTP status code to be used in response.
Note that values may be added to this enum, implementations
must ensure that unknown values will not cause a crash.
Unknown values here must result in the implementation setting the
Accepted Condition for the Route to `status: False`, with a
Reason of `UnsupportedValue`.
Support: Core | 302 | Enum: [301 302]
| + + +#### HTTPRoute + + + +HTTPRoute provides a way to route HTTP requests. This includes the capability +to match requests by hostname, path, header, or query param. Filters can be +used to specify additional processing steps. Backends specify where matching +requests should be routed. + + + +_Appears in:_ +- [HTTPRoute](#httproute) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1` | | | +| `kind` _string_ | `HTTPRoute` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[HTTPRouteSpec](#httproutespec)_ | Spec defines the desired state of HTTPRoute. | | | +| `status` _[HTTPRouteStatus](#httproutestatus)_ | Status defines the current state of HTTPRoute. | | | + + +#### HTTPRouteFilter + + + +HTTPRouteFilter defines processing steps that must be completed during the +request or response lifecycle. HTTPRouteFilters are meant as an extension +point to express processing that may be done in Gateway implementations. Some +examples include request or response modification, implementing +authentication strategies, rate-limiting, and traffic shaping. API +guarantee/conformance is defined based on the type of the filter. + + + + + + +_Appears in:_ +- [HTTPBackendRef](#httpbackendref) +- [HTTPRouteRule](#httprouterule) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[HTTPRouteFilterType](#httproutefiltertype)_ | Type identifies the type of filter to apply. As with other API fields,
types are classified into three conformance levels:
- Core: Filter types and their corresponding configuration defined by
"Support: Core" in this package, e.g. "RequestHeaderModifier". All
implementations must support core filters.
- Extended: Filter types and their corresponding configuration defined by
"Support: Extended" in this package, e.g. "RequestMirror". Implementers
are encouraged to support extended filters.
- Implementation-specific: Filters that are defined and supported by
specific vendors.
In the future, filters showing convergence in behavior across multiple
implementations will be considered for inclusion in extended or core
conformance levels. Filter-specific configuration for such filters
is specified using the ExtensionRef field. `Type` should be set to
"ExtensionRef" for custom filters.
Implementers are encouraged to define custom implementation types to
extend the core API with implementation-specific behavior.
If a reference to a custom filter type cannot be resolved, the filter
MUST NOT be skipped. Instead, requests that would have been processed by
that filter MUST receive a HTTP error response.
Note that values may be added to this enum, implementations
must ensure that unknown values will not cause a crash.
Unknown values here must result in the implementation setting the
Accepted Condition for the Route to `status: False`, with a
Reason of `UnsupportedValue`.
| | Enum: [RequestHeaderModifier ResponseHeaderModifier RequestMirror RequestRedirect URLRewrite ExtensionRef]
| +| `requestHeaderModifier` _[HTTPHeaderFilter](#httpheaderfilter)_ | RequestHeaderModifier defines a schema for a filter that modifies request
headers.
Support: Core | | | +| `responseHeaderModifier` _[HTTPHeaderFilter](#httpheaderfilter)_ | ResponseHeaderModifier defines a schema for a filter that modifies response
headers.
Support: Extended | | | +| `requestMirror` _[HTTPRequestMirrorFilter](#httprequestmirrorfilter)_ | RequestMirror defines a schema for a filter that mirrors requests.
Requests are sent to the specified destination, but responses from
that destination are ignored.
This filter can be used multiple times within the same rule. Note that
not all implementations will be able to support mirroring to multiple
backends.
Support: Extended | | | +| `requestRedirect` _[HTTPRequestRedirectFilter](#httprequestredirectfilter)_ | RequestRedirect defines a schema for a filter that responds to the
request with an HTTP redirection.
Support: Core | | | +| `urlRewrite` _[HTTPURLRewriteFilter](#httpurlrewritefilter)_ | URLRewrite defines a schema for a filter that modifies a request during forwarding.
Support: Extended | | | +| `cors` _[HTTPCORSFilter](#httpcorsfilter)_ | CORS defines a schema for a filter that responds to the
cross-origin request based on HTTP response header.
Support: Extended
| | | +| `extensionRef` _[LocalObjectReference](#localobjectreference)_ | ExtensionRef is an optional, implementation-specific extension to the
"filter" behavior. For example, resource "myroutefilter" in group
"networking.example.net"). ExtensionRef MUST NOT be used for core and
extended filters.
This filter can be used multiple times within the same rule.
Support: Implementation-specific | | | + + +#### HTTPRouteFilterType + +_Underlying type:_ _string_ + +HTTPRouteFilterType identifies a type of HTTPRoute filter. + + + +_Appears in:_ +- [HTTPRouteFilter](#httproutefilter) + +| Field | Description | +| --- | --- | +| `RequestHeaderModifier` | HTTPRouteFilterRequestHeaderModifier can be used to add or remove an HTTP
header from an HTTP request before it is sent to the upstream target.
Support in HTTPRouteRule: Core
Support in HTTPBackendRef: Extended
| +| `ResponseHeaderModifier` | HTTPRouteFilterResponseHeaderModifier can be used to add or remove an HTTP
header from an HTTP response before it is sent to the client.
Support in HTTPRouteRule: Extended
Support in HTTPBackendRef: Extended
| +| `RequestRedirect` | HTTPRouteFilterRequestRedirect can be used to redirect a request to
another location. This filter can also be used for HTTP to HTTPS
redirects. This may not be used on the same Route rule or BackendRef as a
URLRewrite filter.
Support in HTTPRouteRule: Core
Support in HTTPBackendRef: Extended
| +| `URLRewrite` | HTTPRouteFilterURLRewrite can be used to modify a request during
forwarding. At most one of these filters may be used on a Route rule.
This may not be used on the same Route rule or BackendRef as a
RequestRedirect filter.
Support in HTTPRouteRule: Extended
Support in HTTPBackendRef: Extended
| +| `RequestMirror` | HTTPRouteFilterRequestMirror can be used to mirror HTTP requests to a
different backend. The responses from this backend MUST be ignored by
the Gateway.
Support in HTTPRouteRule: Extended
Support in HTTPBackendRef: Extended
| +| `CORS` | HTTPRouteFilterCORS can be used to add CORS headers to an
HTTP response before it is sent to the client.
Support in HTTPRouteRule: Extended
Support in HTTPBackendRef: Extended

| +| `ExtensionRef` | HTTPRouteFilterExtensionRef should be used for configuring custom
HTTP filters.
Support in HTTPRouteRule: Implementation-specific
Support in HTTPBackendRef: Implementation-specific
| + + +#### HTTPRouteMatch + + + +HTTPRouteMatch defines the predicate used to match requests to a given +action. Multiple match types are ANDed together, i.e. the match will +evaluate to true only if all conditions are satisfied. + +For example, the match below will match a HTTP request only if its path +starts with `/foo` AND it contains the `version: v1` header: + +``` +match: + + path: + value: "/foo" + headers: + - name: "version" + value "v1" + +``` + + + +_Appears in:_ +- [HTTPRouteRule](#httprouterule) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `path` _[HTTPPathMatch](#httppathmatch)_ | Path specifies a HTTP request path matcher. If this field is not
specified, a default prefix match on the "/" path is provided. | \{ type:PathPrefix value:/ \} | | +| `headers` _[HTTPHeaderMatch](#httpheadermatch) array_ | Headers specifies HTTP request header matchers. Multiple match values are
ANDed together, meaning, a request must match all the specified headers
to select the route. | | MaxItems: 16
| +| `queryParams` _[HTTPQueryParamMatch](#httpqueryparammatch) array_ | QueryParams specifies HTTP query parameter matchers. Multiple match
values are ANDed together, meaning, a request must match all the
specified query parameters to select the route.
Support: Extended | | MaxItems: 16
| +| `method` _[HTTPMethod](#httpmethod)_ | Method specifies HTTP method matcher.
When specified, this route will be matched only if the request has the
specified method.
Support: Extended | | Enum: [GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATCH]
| + + +#### HTTPRouteRetry + + + +HTTPRouteRetry defines retry configuration for an HTTPRoute. + +Implementations SHOULD retry on connection errors (disconnect, reset, timeout, +TCP failure) if a retry stanza is configured. + + + +_Appears in:_ +- [HTTPRouteRule](#httprouterule) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `codes` _[HTTPRouteRetryStatusCode](#httprouteretrystatuscode) array_ | Codes defines the HTTP response status codes for which a backend request
should be retried.
Support: Extended | | Maximum: 599
Minimum: 400
| +| `attempts` _integer_ | Attempts specifies the maximum number of times an individual request
from the gateway to a backend should be retried.
If the maximum number of retries has been attempted without a successful
response from the backend, the Gateway MUST return an error.
When this field is unspecified, the number of times to attempt to retry
a backend request is implementation-specific.
Support: Extended | | | +| `backoff` _[Duration](#duration)_ | Backoff specifies the minimum duration a Gateway should wait between
retry attempts and is represented in Gateway API Duration formatting.
For example, setting the `rules[].retry.backoff` field to the value
`100ms` will cause a backend request to first be retried approximately
100 milliseconds after timing out or receiving a response code configured
to be retryable.
An implementation MAY use an exponential or alternative backoff strategy
for subsequent retry attempts, MAY cap the maximum backoff duration to
some amount greater than the specified minimum, and MAY add arbitrary
jitter to stagger requests, as long as unsuccessful backend requests are
not retried before the configured minimum duration.
If a Request timeout (`rules[].timeouts.request`) is configured on the
route, the entire duration of the initial request and any retry attempts
MUST not exceed the Request timeout duration. If any retry attempts are
still in progress when the Request timeout duration has been reached,
these SHOULD be canceled if possible and the Gateway MUST immediately
return a timeout error.
If a BackendRequest timeout (`rules[].timeouts.backendRequest`) is
configured on the route, any retry attempts which reach the configured
BackendRequest timeout duration without a response SHOULD be canceled if
possible and the Gateway should wait for at least the specified backoff
duration before attempting to retry the backend request again.
If a BackendRequest timeout is _not_ configured on the route, retry
attempts MAY time out after an implementation default duration, or MAY
remain pending until a configured Request timeout or implementation
default duration for total request time is reached.
When this field is unspecified, the time to wait between retry attempts
is implementation-specific.
Support: Extended | | Pattern: `^([0-9]\{1,5\}(h\|m\|s\|ms))\{1,4\}$`
| + + +#### HTTPRouteRetryStatusCode + +_Underlying type:_ _integer_ + +HTTPRouteRetryStatusCode defines an HTTP response status code for +which a backend request should be retried. + +Implementations MUST support the following status codes as retryable: + +* 500 +* 502 +* 503 +* 504 + +Implementations MAY support specifying additional discrete values in the +500-599 range. + +Implementations MAY support specifying discrete values in the 400-499 range, +which are often inadvisable to retry. + + + +_Validation:_ +- Maximum: 599 +- Minimum: 400 + +_Appears in:_ +- [HTTPRouteRetry](#httprouteretry) + + + +#### HTTPRouteRule + + + +HTTPRouteRule defines semantics for matching an HTTP request based on +conditions (matches), processing it (filters), and forwarding the request to +an API object (backendRefs). + + + +_Appears in:_ +- [HTTPRouteSpec](#httproutespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _[SectionName](#sectionname)_ | Name is the name of the route rule. This name MUST be unique within a Route if it is set.
Support: Extended
| | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `matches` _[HTTPRouteMatch](#httproutematch) array_ | Matches define conditions used for matching the rule against incoming
HTTP requests. Each match is independent, i.e. this rule will be matched
if **any** one of the matches is satisfied.
For example, take the following matches configuration:
```
matches:
- path:
value: "/foo"
headers:
- name: "version"
value: "v2"
- path:
value: "/v2/foo"
```
For a request to match against this rule, a request must satisfy
EITHER of the two conditions:
- path prefixed with `/foo` AND contains the header `version: v2`
- path prefix of `/v2/foo`
See the documentation for HTTPRouteMatch on how to specify multiple
match conditions that should be ANDed together.
If no matches are specified, the default is a prefix
path match on "/", which has the effect of matching every
HTTP request.
Proxy or Load Balancer routing configuration generated from HTTPRoutes
MUST prioritize matches based on the following criteria, continuing on
ties. Across all rules specified on applicable Routes, precedence must be
given to the match having:
* "Exact" path match.
* "Prefix" path match with largest number of characters.
* Method match.
* Largest number of header matches.
* Largest number of query param matches.
Note: The precedence of RegularExpression path matches are implementation-specific.
If ties still exist across multiple Routes, matching precedence MUST be
determined in order of the following criteria, continuing on ties:
* The oldest Route based on creation timestamp.
* The Route appearing first in alphabetical order by
"\{namespace\}/\{name\}".
If ties still exist within an HTTPRoute, matching precedence MUST be granted
to the FIRST matching rule (in list order) with a match meeting the above
criteria.
When no rules matching a request have been successfully attached to the
parent a request is coming from, a HTTP 404 status code MUST be returned. | [map[path:map[type:PathPrefix value:/]]] | MaxItems: 64
| +| `filters` _[HTTPRouteFilter](#httproutefilter) array_ | Filters define the filters that are applied to requests that match
this rule.
Wherever possible, implementations SHOULD implement filters in the order
they are specified.
Implementations MAY choose to implement this ordering strictly, rejecting
any combination or order of filters that cannot be supported. If implementations
choose a strict interpretation of filter ordering, they MUST clearly document
that behavior.
To reject an invalid combination or order of filters, implementations SHOULD
consider the Route Rules with this configuration invalid. If all Route Rules
in a Route are invalid, the entire Route would be considered invalid. If only
a portion of Route Rules are invalid, implementations MUST set the
"PartiallyInvalid" condition for the Route.
Conformance-levels at this level are defined based on the type of filter:
- ALL core filters MUST be supported by all implementations.
- Implementers are encouraged to support extended filters.
- Implementation-specific custom filters have no API guarantees across
implementations.
Specifying the same filter multiple times is not supported unless explicitly
indicated in the filter.
All filters are expected to be compatible with each other except for the
URLRewrite and RequestRedirect filters, which may not be combined. If an
implementation cannot support other combinations of filters, they must clearly
document that limitation. In cases where incompatible or unsupported
filters are specified and cause the `Accepted` condition to be set to status
`False`, implementations may use the `IncompatibleFilters` reason to specify
this configuration error.
Support: Core | | MaxItems: 16
| +| `backendRefs` _[HTTPBackendRef](#httpbackendref) array_ | BackendRefs defines the backend(s) where matching requests should be
sent.
Failure behavior here depends on how many BackendRefs are specified and
how many are invalid.
If *all* entries in BackendRefs are invalid, and there are also no filters
specified in this route rule, *all* traffic which matches this rule MUST
receive a 500 status code.
See the HTTPBackendRef definition for the rules about what makes a single
HTTPBackendRef invalid.
When a HTTPBackendRef is invalid, 500 status codes MUST be returned for
requests that would have otherwise been routed to an invalid backend. If
multiple backends are specified, and some are invalid, the proportion of
requests that would otherwise have been routed to an invalid backend
MUST receive a 500 status code.
For example, if two backends are specified with equal weights, and one is
invalid, 50 percent of traffic must receive a 500. Implementations may
choose how that 50 percent is determined.
When a HTTPBackendRef refers to a Service that has no ready endpoints,
implementations SHOULD return a 503 for requests to that backend instead.
If an implementation chooses to do this, all of the above rules for 500 responses
MUST also apply for responses that return a 503.
Support: Core for Kubernetes Service
Support: Extended for Kubernetes ServiceImport
Support: Implementation-specific for any other resource
Support for weight: Core | | MaxItems: 16
| +| `timeouts` _[HTTPRouteTimeouts](#httproutetimeouts)_ | Timeouts defines the timeouts that can be configured for an HTTP request.
Support: Extended | | | +| `retry` _[HTTPRouteRetry](#httprouteretry)_ | Retry defines the configuration for when to retry an HTTP request.
Support: Extended
| | | +| `sessionPersistence` _[SessionPersistence](#sessionpersistence)_ | SessionPersistence defines and configures session persistence
for the route rule.
Support: Extended
| | | + + +#### HTTPRouteSpec + + + +HTTPRouteSpec defines the desired state of HTTPRoute + + + +_Appears in:_ +- [HTTPRoute](#httproute) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `parentRefs` _[ParentReference](#parentreference) array_ | ParentRefs references the resources (usually Gateways) that a Route wants
to be attached to. Note that the referenced parent resource needs to
allow this for the attachment to be complete. For Gateways, that means
the Gateway needs to allow attachment from Routes of this kind and
namespace. For Services, that means the Service must either be in the same
namespace for a "producer" route, or the mesh implementation must support
and allow "consumer" routes for the referenced Service. ReferenceGrant is
not applicable for governing ParentRefs to Services - it is not possible to
create a "producer" route for a Service in a different namespace from the
Route.
There are two kinds of parent resources with "Core" support:
* Gateway (Gateway conformance profile)
* Service (Mesh conformance profile, ClusterIP Services only)
This API may be extended in the future to support additional kinds of parent
resources.
ParentRefs must be _distinct_. This means either that:
* They select different objects. If this is the case, then parentRef
entries are distinct. In terms of fields, this means that the
multi-part key defined by `group`, `kind`, `namespace`, and `name` must
be unique across all parentRef entries in the Route.
* They do not select different objects, but for each optional field used,
each ParentRef that selects the same object must set the same set of
optional fields to different values. If one ParentRef sets a
combination of optional fields, all must set the same combination.
Some examples:
* If one ParentRef sets `sectionName`, all ParentRefs referencing the
same object must also set `sectionName`.
* If one ParentRef sets `port`, all ParentRefs referencing the same
object must also set `port`.
* If one ParentRef sets `sectionName` and `port`, all ParentRefs
referencing the same object must also set `sectionName` and `port`.
It is possible to separately reference multiple distinct objects that may
be collapsed by an implementation. For example, some implementations may
choose to merge compatible Gateway Listeners together. If that is the
case, the list of routes attached to those resources should also be
merged.
Note that for ParentRefs that cross namespace boundaries, there are specific
rules. Cross-namespace references are only valid if they are explicitly
allowed by something in the namespace they are referring to. For example,
Gateway has the AllowedRoutes field, and ReferenceGrant provides a
generic way to enable other kinds of cross-namespace reference.

ParentRefs from a Route to a Service in the same namespace are "producer"
routes, which apply default routing rules to inbound connections from
any namespace to the Service.
ParentRefs from a Route to a Service in a different namespace are
"consumer" routes, and these routing rules are only applied to outbound
connections originating from the same namespace as the Route, for which
the intended destination of the connections are a Service targeted as a
ParentRef of the Route.




| | MaxItems: 32
| +| `hostnames` _[Hostname](#hostname) array_ | Hostnames defines a set of hostnames that should match against the HTTP Host
header to select a HTTPRoute used to process the request. Implementations
MUST ignore any port value specified in the HTTP Host header while
performing a match and (absent of any applicable header modification
configuration) MUST forward this header unmodified to the backend.
Valid values for Hostnames are determined by RFC 1123 definition of a
hostname with 2 notable exceptions:
1. IPs are not allowed.
2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard
label must appear by itself as the first label.
If a hostname is specified by both the Listener and HTTPRoute, there
must be at least one intersecting hostname for the HTTPRoute to be
attached to the Listener. For example:
* A Listener with `test.example.com` as the hostname matches HTTPRoutes
that have either not specified any hostnames, or have specified at
least one of `test.example.com` or `*.example.com`.
* A Listener with `*.example.com` as the hostname matches HTTPRoutes
that have either not specified any hostnames or have specified at least
one hostname that matches the Listener hostname. For example,
`*.example.com`, `test.example.com`, and `foo.test.example.com` would
all match. On the other hand, `example.com` and `test.example.net` would
not match.
Hostnames that are prefixed with a wildcard label (`*.`) are interpreted
as a suffix match. That means that a match for `*.example.com` would match
both `test.example.com`, and `foo.test.example.com`, but not `example.com`.
If both the Listener and HTTPRoute have specified hostnames, any
HTTPRoute hostnames that do not match the Listener hostname MUST be
ignored. For example, if a Listener specified `*.example.com`, and the
HTTPRoute specified `test.example.com` and `test.example.net`,
`test.example.net` must not be considered for a match.
If both the Listener and HTTPRoute have specified hostnames, and none
match with the criteria above, then the HTTPRoute is not accepted. The
implementation must raise an 'Accepted' Condition with a status of
`False` in the corresponding RouteParentStatus.
In the event that multiple HTTPRoutes specify intersecting hostnames (e.g.
overlapping wildcard matching and exact matching hostnames), precedence must
be given to rules from the HTTPRoute with the largest number of:
* Characters in a matching non-wildcard hostname.
* Characters in a matching hostname.
If ties exist across multiple Routes, the matching precedence rules for
HTTPRouteMatches takes over.
Support: Core | | MaxItems: 16
MaxLength: 253
MinLength: 1
Pattern: `^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `rules` _[HTTPRouteRule](#httprouterule) array_ | Rules are a list of HTTP matchers, filters and actions.
| [map[matches:[map[path:map[type:PathPrefix value:/]]]]] | MaxItems: 16
| + + +#### HTTPRouteStatus + + + +HTTPRouteStatus defines the observed state of HTTPRoute. + + + +_Appears in:_ +- [HTTPRoute](#httproute) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `parents` _[RouteParentStatus](#routeparentstatus) array_ | Parents is a list of parent resources (usually Gateways) that are
associated with the route, and the status of the route with respect to
each parent. When this route attaches to a parent, the controller that
manages the parent must add an entry to this list when the controller
first sees the route and should update the entry as appropriate when the
route or gateway is modified.
Note that parent references that cannot be resolved by an implementation
of this API will not be added to this list. Implementations of this API
can only populate Route status for the Gateways/parent resources they are
responsible for.
A maximum of 32 Gateways will be represented in this list. An empty list
means the route has not been attached to any Gateway. | | MaxItems: 32
| + + +#### HTTPRouteTimeouts + + + +HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute. +Timeout values are represented with Gateway API Duration formatting. + + + +_Appears in:_ +- [HTTPRouteRule](#httprouterule) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `request` _[Duration](#duration)_ | Request specifies the maximum duration for a gateway to respond to an HTTP request.
If the gateway has not been able to respond before this deadline is met, the gateway
MUST return a timeout error.
For example, setting the `rules.timeouts.request` field to the value `10s` in an
`HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds
to complete.
Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout
completely. Implementations that cannot completely disable the timeout MUST
instead interpret the zero duration as the longest possible value to which
the timeout can be set.
This timeout is intended to cover as close to the whole request-response transaction
as possible although an implementation MAY choose to start the timeout after the entire
request stream has been received instead of immediately after the transaction is
initiated by the client.
The value of Request is a Gateway API Duration string as defined by GEP-2257. When this
field is unspecified, request timeout behavior is implementation-specific.
Support: Extended | | Pattern: `^([0-9]\{1,5\}(h\|m\|s\|ms))\{1,4\}$`
| +| `backendRequest` _[Duration](#duration)_ | BackendRequest specifies a timeout for an individual request from the gateway
to a backend. This covers the time from when the request first starts being
sent from the gateway to when the full response has been received from the backend.
Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout
completely. Implementations that cannot completely disable the timeout MUST
instead interpret the zero duration as the longest possible value to which
the timeout can be set.
An entire client HTTP transaction with a gateway, covered by the Request timeout,
may result in more than one call from the gateway to the destination backend,
for example, if automatic retries are supported.
The value of BackendRequest must be a Gateway API Duration string as defined by
GEP-2257. When this field is unspecified, its behavior is implementation-specific;
when specified, the value of BackendRequest must be no more than the value of the
Request timeout (since the Request timeout encompasses the BackendRequest timeout).
Support: Extended | | Pattern: `^([0-9]\{1,5\}(h\|m\|s\|ms))\{1,4\}$`
| + + +#### HTTPURLRewriteFilter + + + +HTTPURLRewriteFilter defines a filter that modifies a request during +forwarding. At most one of these filters may be used on a Route rule. This +MUST NOT be used on the same Route rule as a HTTPRequestRedirect filter. + +Support: Extended + + + +_Appears in:_ +- [HTTPRouteFilter](#httproutefilter) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `hostname` _[PreciseHostname](#precisehostname)_ | Hostname is the value to be used to replace the Host header value during
forwarding.
Support: Extended | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `path` _[HTTPPathModifier](#httppathmodifier)_ | Path defines a path rewrite.
Support: Extended | | | + + +#### HeaderMatchType + +_Underlying type:_ _string_ + +HeaderMatchType specifies the semantics of how HTTP header values should be +compared. Valid HeaderMatchType values, along with their conformance levels, are: + +* "Exact" - Core +* "RegularExpression" - Implementation Specific + +Note that values may be added to this enum, implementations +must ensure that unknown values will not cause a crash. + +Unknown values here must result in the implementation setting the +Accepted Condition for the Route to `status: False`, with a +Reason of `UnsupportedValue`. + +_Validation:_ +- Enum: [Exact RegularExpression] + +_Appears in:_ +- [HTTPHeaderMatch](#httpheadermatch) + +| Field | Description | +| --- | --- | +| `Exact` | | +| `RegularExpression` | | + + +#### HeaderName + +_Underlying type:_ _string_ + +HeaderName is the name of a header or query parameter. + +_Validation:_ +- MaxLength: 256 +- MinLength: 1 +- Pattern: `^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$` + +_Appears in:_ +- [GRPCHeaderName](#grpcheadername) +- [HTTPHeaderName](#httpheadername) + + + +#### Hostname + +_Underlying type:_ _string_ + +Hostname is the fully qualified domain name of a network host. This matches +the RFC 1123 definition of a hostname with 2 notable exceptions: + + 1. IPs are not allowed. + 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + label must appear by itself as the first label. + +Hostname can be "precise" which is a domain name without the terminating +dot of a network host (e.g. "foo.example.com") or "wildcard", which is a +domain name prefixed with a single wildcard label (e.g. `*.example.com`). + +Note that as per RFC1035 and RFC1123, a *label* must consist of lower case +alphanumeric characters or '-', and must start and end with an alphanumeric +character. No other punctuation is allowed. + +_Validation:_ +- MaxLength: 253 +- MinLength: 1 +- Pattern: `^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` + +_Appears in:_ +- [GRPCRouteSpec](#grpcroutespec) +- [HTTPRouteSpec](#httproutespec) +- [Listener](#listener) +- [SubjectAltName](#subjectaltname) + + + +#### Kind + +_Underlying type:_ _string_ + +Kind refers to a Kubernetes Kind. + +Valid values include: + +* "Service" +* "HTTPRoute" + +Invalid values include: + +* "invalid/kind" - "/" is an invalid character + +_Validation:_ +- MaxLength: 63 +- MinLength: 1 +- Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` + +_Appears in:_ +- [BackendObjectReference](#backendobjectreference) +- [BackendRef](#backendref) +- [GRPCBackendRef](#grpcbackendref) +- [HTTPBackendRef](#httpbackendref) +- [LocalObjectReference](#localobjectreference) +- [LocalParametersReference](#localparametersreference) +- [ObjectReference](#objectreference) +- [ParametersReference](#parametersreference) +- [ParentReference](#parentreference) +- [RouteGroupKind](#routegroupkind) +- [SecretObjectReference](#secretobjectreference) + + + +#### LabelKey + +_Underlying type:_ _string_ + +LabelKey is the key of a label in the Gateway API. This is used for validation +of maps such as Gateway infrastructure labels. This matches the Kubernetes +"qualified name" validation that is used for labels. + +Valid values include: + +* example +* example.com +* example.com/path +* example.com/path.html + +Invalid values include: + +* example~ - "~" is an invalid character +* example.com. - cannot start or end with "." + +_Validation:_ +- MaxLength: 253 +- MinLength: 1 +- Pattern: `^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?([A-Za-z0-9][-A-Za-z0-9_.]{0,61})?[A-Za-z0-9]$` + +_Appears in:_ +- [GatewayInfrastructure](#gatewayinfrastructure) + + + +#### LabelValue + +_Underlying type:_ _string_ + +LabelValue is the value of a label in the Gateway API. This is used for validation +of maps such as Gateway infrastructure labels. This matches the Kubernetes +label validation rules: +* must be 63 characters or less (can be empty), +* unless empty, must begin and end with an alphanumeric character ([a-z0-9A-Z]), +* could contain dashes (-), underscores (_), dots (.), and alphanumerics between. + +Valid values include: + +* MyValue +* my.name +* 123-my-value + +_Validation:_ +- MaxLength: 63 +- MinLength: 0 +- Pattern: `^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$` + +_Appears in:_ +- [GatewayInfrastructure](#gatewayinfrastructure) + + + +#### Listener + + + +Listener embodies the concept of a logical endpoint where a Gateway accepts +network connections. + + + +_Appears in:_ +- [GatewaySpec](#gatewayspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _[SectionName](#sectionname)_ | Name is the name of the Listener. This name MUST be unique within a
Gateway.
Support: Core | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `hostname` _[Hostname](#hostname)_ | Hostname specifies the virtual hostname to match for protocol types that
define this concept. When unspecified, all hostnames are matched. This
field is ignored for protocols that don't require hostname based
matching.
Implementations MUST apply Hostname matching appropriately for each of
the following protocols:
* TLS: The Listener Hostname MUST match the SNI.
* HTTP: The Listener Hostname MUST match the Host header of the request.
* HTTPS: The Listener Hostname SHOULD match both the SNI and Host header.
Note that this does not require the SNI and Host header to be the same.
The semantics of this are described in more detail below.
To ensure security, Section 11.1 of RFC-6066 emphasizes that server
implementations that rely on SNI hostname matching MUST also verify
hostnames within the application protocol.
Section 9.1.2 of RFC-7540 provides a mechanism for servers to reject the
reuse of a connection by responding with the HTTP 421 Misdirected Request
status code. This indicates that the origin server has rejected the
request because it appears to have been misdirected.
To detect misdirected requests, Gateways SHOULD match the authority of
the requests with all the SNI hostname(s) configured across all the
Gateway Listeners on the same port and protocol:
* If another Listener has an exact match or more specific wildcard entry,
the Gateway SHOULD return a 421.
* If the current Listener (selected by SNI matching during ClientHello)
does not match the Host:
* If another Listener does match the Host the Gateway SHOULD return a
421.
* If no other Listener matches the Host, the Gateway MUST return a
404.
For HTTPRoute and TLSRoute resources, there is an interaction with the
`spec.hostnames` array. When both listener and route specify hostnames,
there MUST be an intersection between the values for a Route to be
accepted. For more information, refer to the Route specific Hostnames
documentation.
Hostnames that are prefixed with a wildcard label (`*.`) are interpreted
as a suffix match. That means that a match for `*.example.com` would match
both `test.example.com`, and `foo.test.example.com`, but not `example.com`.
Support: Core | | MaxLength: 253
MinLength: 1
Pattern: `^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `port` _[PortNumber](#portnumber)_ | Port is the network port. Multiple listeners may use the
same port, subject to the Listener compatibility rules.
Support: Core | | Maximum: 65535
Minimum: 1
| +| `protocol` _[ProtocolType](#protocoltype)_ | Protocol specifies the network protocol this listener expects to receive.
Support: Core | | MaxLength: 255
MinLength: 1
Pattern: `^[a-zA-Z0-9]([-a-zA-Z0-9]*[a-zA-Z0-9])?$\|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$`
| +| `tls` _[GatewayTLSConfig](#gatewaytlsconfig)_ | TLS is the TLS configuration for the Listener. This field is required if
the Protocol field is "HTTPS" or "TLS". It is invalid to set this field
if the Protocol field is "HTTP", "TCP", or "UDP".
The association of SNIs to Certificate defined in GatewayTLSConfig is
defined based on the Hostname field for this listener.
The GatewayClass MUST use the longest matching SNI out of all
available certificates for any TLS handshake.
Support: Core | | | +| `allowedRoutes` _[AllowedRoutes](#allowedroutes)_ | AllowedRoutes defines the types of routes that MAY be attached to a
Listener and the trusted namespaces where those Route resources MAY be
present.
Although a client request may match multiple route rules, only one rule
may ultimately receive the request. Matching precedence MUST be
determined in order of the following criteria:
* The most specific match as defined by the Route type.
* The oldest Route based on creation timestamp. For example, a Route with
a creation timestamp of "2020-09-08 01:02:03" is given precedence over
a Route with a creation timestamp of "2020-09-08 01:02:04".
* If everything else is equivalent, the Route appearing first in
alphabetical order (namespace/name) should be given precedence. For
example, foo/bar is given precedence over foo/baz.
All valid rules within a Route attached to this Listener should be
implemented. Invalid Route rules can be ignored (sometimes that will mean
the full Route). If a Route rule transitions from valid to invalid,
support for that Route rule should be dropped to ensure consistency. For
example, even if a filter specified by a Route rule is invalid, the rest
of the rules within that Route should still be supported.
Support: Core | \{ namespaces:map[from:Same] \} | | + + + + + + +#### ListenerNamespaces + + + +ListenerNamespaces indicate which namespaces ListenerSets should be selected from. + + + +_Appears in:_ +- [AllowedListeners](#allowedlisteners) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `from` _[FromNamespaces](#fromnamespaces)_ | From indicates where ListenerSets can attach to this Gateway. Possible
values are:
* Same: Only ListenerSets in the same namespace may be attached to this Gateway.
* Selector: ListenerSets in namespaces selected by the selector may be attached to this Gateway.
* All: ListenerSets in all namespaces may be attached to this Gateway.
* None: Only listeners defined in the Gateway's spec are allowed
While this feature is experimental, the default value None | None | Enum: [All Selector Same None]
| +| `selector` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#labelselector-v1-meta)_ | Selector must be specified when From is set to "Selector". In that case,
only ListenerSets in Namespaces matching this Selector will be selected by this
Gateway. This field is ignored for other values of "From". | | | + + +#### ListenerStatus + + + +ListenerStatus is the status associated with a Listener. + + + +_Appears in:_ +- [GatewayStatus](#gatewaystatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _[SectionName](#sectionname)_ | Name is the name of the Listener that this status corresponds to. | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `supportedKinds` _[RouteGroupKind](#routegroupkind) array_ | SupportedKinds is the list indicating the Kinds supported by this
listener. This MUST represent the kinds an implementation supports for
that Listener configuration.
If kinds are specified in Spec that are not supported, they MUST NOT
appear in this list and an implementation MUST set the "ResolvedRefs"
condition to "False" with the "InvalidRouteKinds" reason. If both valid
and invalid Route kinds are specified, the implementation MUST
reference the valid Route kinds that have been specified. | | MaxItems: 8
| +| `attachedRoutes` _integer_ | AttachedRoutes represents the total number of Routes that have been
successfully attached to this Listener.
Successful attachment of a Route to a Listener is based solely on the
combination of the AllowedRoutes field on the corresponding Listener
and the Route's ParentRefs field. A Route is successfully attached to
a Listener when it is selected by the Listener's AllowedRoutes field
AND the Route has a valid ParentRef selecting the whole Gateway
resource or a specific Listener as a parent resource (more detail on
attachment semantics can be found in the documentation on the various
Route kinds ParentRefs fields). Listener or Route status does not impact
successful attachment, i.e. the AttachedRoutes field count MUST be set
for Listeners with condition Accepted: false and MUST count successfully
attached Routes that may themselves have Accepted: false conditions.
Uses for this field include troubleshooting Route attachment and
measuring blast radius/impact of changes to a Listener. | | | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#condition-v1-meta) array_ | Conditions describe the current condition of this listener. | | MaxItems: 8
| + + +#### LocalObjectReference + + + +LocalObjectReference identifies an API object within the namespace of the +referrer. +The API object must be valid in the cluster; the Group and Kind must +be registered in the cluster for this reference to be valid. + +References to objects with invalid Group and Kind are not valid, and must +be rejected by the implementation, with appropriate Conditions set +on the containing object. + + + +_Appears in:_ +- [BackendTLSPolicyValidation](#backendtlspolicyvalidation) +- [GRPCRouteFilter](#grpcroutefilter) +- [HTTPRouteFilter](#httproutefilter) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent. For example, "gateway.networking.k8s.io".
When unspecified or empty string, core API group is inferred. | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is kind of the referent. For example "HTTPRoute" or "Service". | | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. | | MaxLength: 253
MinLength: 1
| + + +#### LocalParametersReference + + + +LocalParametersReference identifies an API object containing controller-specific +configuration resource within the namespace. + + + +_Appears in:_ +- [GatewayInfrastructure](#gatewayinfrastructure) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent. | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is kind of the referent. | | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _string_ | Name is the name of the referent. | | MaxLength: 253
MinLength: 1
| + + +#### Namespace + +_Underlying type:_ _string_ + +Namespace refers to a Kubernetes namespace. It must be a RFC 1123 label. + +This validation is based off of the corresponding Kubernetes validation: +https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L187 + +This is used for Namespace name validation here: +https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/api/validation/generic.go#L63 + +Valid values include: + +* "example" + +Invalid values include: + +* "example.com" - "." is an invalid character + +_Validation:_ +- MaxLength: 63 +- MinLength: 1 +- Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` + +_Appears in:_ +- [BackendObjectReference](#backendobjectreference) +- [BackendRef](#backendref) +- [GRPCBackendRef](#grpcbackendref) +- [HTTPBackendRef](#httpbackendref) +- [ObjectReference](#objectreference) +- [ParametersReference](#parametersreference) +- [ParentReference](#parentreference) +- [SecretObjectReference](#secretobjectreference) + + + +#### ObjectName + +_Underlying type:_ _string_ + +ObjectName refers to the name of a Kubernetes object. +Object names can have a variety of forms, including RFC 1123 subdomains, +RFC 1123 labels, or RFC 1035 labels. + +_Validation:_ +- MaxLength: 253 +- MinLength: 1 + +_Appears in:_ +- [BackendObjectReference](#backendobjectreference) +- [BackendRef](#backendref) +- [GRPCBackendRef](#grpcbackendref) +- [GatewaySpec](#gatewayspec) +- [HTTPBackendRef](#httpbackendref) +- [LocalObjectReference](#localobjectreference) +- [ObjectReference](#objectreference) +- [ParentReference](#parentreference) +- [SecretObjectReference](#secretobjectreference) + + + +#### ObjectReference + + + +ObjectReference identifies an API object including its namespace. + +The API object must be valid in the cluster; the Group and Kind must +be registered in the cluster for this reference to be valid. + +References to objects with invalid Group and Kind are not valid, and must +be rejected by the implementation, with appropriate Conditions set +on the containing object. + + + +_Appears in:_ +- [FrontendTLSValidation](#frontendtlsvalidation) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent. For example, "gateway.networking.k8s.io".
When set to the empty string, core API group is inferred. | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is kind of the referent. For example "ConfigMap" or "Service". | | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. | | MaxLength: 253
MinLength: 1
| +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referenced object. When unspecified, the local
namespace is inferred.
Note that when a namespace different than the local namespace is specified,
a ReferenceGrant object is required in the referent namespace to allow that
namespace's owner to accept the reference. See the ReferenceGrant
documentation for details.
Support: Core | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| + + +#### ParametersReference + + + +ParametersReference identifies an API object containing controller-specific +configuration resource within the cluster. + + + +_Appears in:_ +- [GatewayClassSpec](#gatewayclassspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent. | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is kind of the referent. | | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _string_ | Name is the name of the referent. | | MaxLength: 253
MinLength: 1
| +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referent.
This field is required when referring to a Namespace-scoped resource and
MUST be unset when referring to a Cluster-scoped resource. | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| + + +#### ParentReference + + + +ParentReference identifies an API object (usually a Gateway) that can be considered +a parent of this resource (usually a route). There are two kinds of parent resources +with "Core" support: + +* Gateway (Gateway conformance profile) +* Service (Mesh conformance profile, ClusterIP Services only) + +This API may be extended in the future to support additional kinds of parent +resources. + +The API object must be valid in the cluster; the Group and Kind must +be registered in the cluster for this reference to be valid. + + + +_Appears in:_ +- [CommonRouteSpec](#commonroutespec) +- [GRPCRouteSpec](#grpcroutespec) +- [HTTPRouteSpec](#httproutespec) +- [RouteParentStatus](#routeparentstatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent.
When unspecified, "gateway.networking.k8s.io" is inferred.
To set the core API group (such as for a "Service" kind referent),
Group must be explicitly set to "" (empty string).
Support: Core | gateway.networking.k8s.io | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is kind of the referent.
There are two kinds of parent resources with "Core" support:
* Gateway (Gateway conformance profile)
* Service (Mesh conformance profile, ClusterIP Services only)
Support for other resources is Implementation-Specific. | Gateway | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referent. When unspecified, this refers
to the local namespace of the Route.
Note that there are specific rules for ParentRefs which cross namespace
boundaries. Cross-namespace references are only valid if they are explicitly
allowed by something in the namespace they are referring to. For example:
Gateway has the AllowedRoutes field, and ReferenceGrant provides a
generic way to enable any other kind of cross-namespace reference.

ParentRefs from a Route to a Service in the same namespace are "producer"
routes, which apply default routing rules to inbound connections from
any namespace to the Service.
ParentRefs from a Route to a Service in a different namespace are
"consumer" routes, and these routing rules are only applied to outbound
connections originating from the same namespace as the Route, for which
the intended destination of the connections are a Service targeted as a
ParentRef of the Route.

Support: Core | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent.
Support: Core | | MaxLength: 253
MinLength: 1
| +| `sectionName` _[SectionName](#sectionname)_ | SectionName is the name of a section within the target resource. In the
following resources, SectionName is interpreted as the following:
* Gateway: Listener name. When both Port (experimental) and SectionName
are specified, the name and port of the selected listener must match
both specified values.
* Service: Port name. When both Port (experimental) and SectionName
are specified, the name and port of the selected listener must match
both specified values.
Implementations MAY choose to support attaching Routes to other resources.
If that is the case, they MUST clearly document how SectionName is
interpreted.
When unspecified (empty string), this will reference the entire resource.
For the purpose of status, an attachment is considered successful if at
least one section in the parent resource accepts it. For example, Gateway
listeners can restrict which Routes can attach to them by Route kind,
namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from
the referencing Route, the Route MUST be considered successfully
attached. If no Gateway listeners accept attachment from this Route, the
Route MUST be considered detached from the Gateway.
Support: Core | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `port` _[PortNumber](#portnumber)_ | Port is the network port this Route targets. It can be interpreted
differently based on the type of parent resource.
When the parent resource is a Gateway, this targets all listeners
listening on the specified port that also support this kind of Route(and
select this Route). It's not recommended to set `Port` unless the
networking behaviors specified in a Route must apply to a specific port
as opposed to a listener(s) whose port(s) may be changed. When both Port
and SectionName are specified, the name and port of the selected listener
must match both specified values.

When the parent resource is a Service, this targets a specific port in the
Service spec. When both Port (experimental) and SectionName are specified,
the name and port of the selected port must match both specified values.

Implementations MAY choose to support other parent resources.
Implementations supporting other types of parent resources MUST clearly
document how/if Port is interpreted.
For the purpose of status, an attachment is considered successful as
long as the parent resource accepts it partially. For example, Gateway
listeners can restrict which Routes can attach to them by Route kind,
namespace, or hostname. If 1 of 2 Gateway listeners accept attachment
from the referencing Route, the Route MUST be considered successfully
attached. If no Gateway listeners accept attachment from this Route,
the Route MUST be considered detached from the Gateway.
Support: Extended | | Maximum: 65535
Minimum: 1
| + + +#### PathMatchType + +_Underlying type:_ _string_ + +PathMatchType specifies the semantics of how HTTP paths should be compared. +Valid PathMatchType values, along with their support levels, are: + +* "Exact" - Core +* "PathPrefix" - Core +* "RegularExpression" - Implementation Specific + +PathPrefix and Exact paths must be syntactically valid: + +- Must begin with the `/` character +- Must not contain consecutive `/` characters (e.g. `/foo///`, `//`). + +Note that values may be added to this enum, implementations +must ensure that unknown values will not cause a crash. + +Unknown values here must result in the implementation setting the +Accepted Condition for the Route to `status: False`, with a +Reason of `UnsupportedValue`. + +_Validation:_ +- Enum: [Exact PathPrefix RegularExpression] + +_Appears in:_ +- [HTTPPathMatch](#httppathmatch) + +| Field | Description | +| --- | --- | +| `Exact` | Matches the URL path exactly and with case sensitivity. This means that
an exact path match on `/abc` will only match requests to `/abc`, NOT
`/abc/`, `/Abc`, or `/abcd`.
| +| `PathPrefix` | Matches based on a URL path prefix split by `/`. Matching is
case-sensitive and done on a path element by element basis. A
path element refers to the list of labels in the path split by
the `/` separator. When specified, a trailing `/` is ignored.
For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match
the prefix `/abc`, but the path `/abcd` would not.
"PathPrefix" is semantically equivalent to the "Prefix" path type in the
Kubernetes Ingress API.
| +| `RegularExpression` | Matches if the URL path matches the given regular expression with
case sensitivity.
Since `"RegularExpression"` has implementation-specific conformance,
implementations can support POSIX, PCRE, RE2 or any other regular expression
dialect.
Please read the implementation's documentation to determine the supported
dialect.
| + + +#### PortNumber + +_Underlying type:_ _integer_ + +PortNumber defines a network port. + +_Validation:_ +- Maximum: 65535 +- Minimum: 1 + +_Appears in:_ +- [BackendObjectReference](#backendobjectreference) +- [BackendRef](#backendref) +- [GRPCBackendRef](#grpcbackendref) +- [HTTPBackendRef](#httpbackendref) +- [HTTPRequestRedirectFilter](#httprequestredirectfilter) +- [Listener](#listener) +- [ParentReference](#parentreference) + + + +#### PreciseHostname + +_Underlying type:_ _string_ + +PreciseHostname is the fully qualified domain name of a network host. This +matches the RFC 1123 definition of a hostname with 1 notable exception that +numeric IP addresses are not allowed. + +Note that as per RFC1035 and RFC1123, a *label* must consist of lower case +alphanumeric characters or '-', and must start and end with an alphanumeric +character. No other punctuation is allowed. + +_Validation:_ +- MaxLength: 253 +- MinLength: 1 +- Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` + +_Appears in:_ +- [BackendTLSPolicyValidation](#backendtlspolicyvalidation) +- [HTTPRequestRedirectFilter](#httprequestredirectfilter) +- [HTTPURLRewriteFilter](#httpurlrewritefilter) + + + +#### ProtocolType + +_Underlying type:_ _string_ + +ProtocolType defines the application protocol accepted by a Listener. +Implementations are not required to accept all the defined protocols. If an +implementation does not support a specified protocol, it MUST set the +"Accepted" condition to False for the affected Listener with a reason of +"UnsupportedProtocol". + +Core ProtocolType values are listed in the table below. + +Implementations can define their own protocols if a core ProtocolType does not +exist. Such definitions must use prefixed name, such as +`mycompany.com/my-custom-protocol`. Un-prefixed names are reserved for core +protocols. Any protocol defined by implementations will fall under +Implementation-specific conformance. + +Valid values include: + +* "HTTP" - Core support +* "example.com/bar" - Implementation-specific support + +Invalid values include: + +* "example.com" - must include path if domain is used +* "foo.example.com" - must include path if domain is used + +_Validation:_ +- MaxLength: 255 +- MinLength: 1 +- Pattern: `^[a-zA-Z0-9]([-a-zA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$` + +_Appears in:_ +- [Listener](#listener) + +| Field | Description | +| --- | --- | +| `HTTP` | Accepts cleartext HTTP/1.1 sessions over TCP. Implementations MAY also
support HTTP/2 over cleartext. If implementations support HTTP/2 over
cleartext on "HTTP" listeners, that MUST be clearly documented by the
implementation.
| +| `HTTPS` | Accepts HTTP/1.1 or HTTP/2 sessions over TLS.
| +| `TLS` | Accepts TLS sessions over TCP.
| +| `TCP` | Accepts TCP sessions.
| +| `UDP` | Accepts UDP packets.
| + + +#### QueryParamMatchType + +_Underlying type:_ _string_ + +QueryParamMatchType specifies the semantics of how HTTP query parameter +values should be compared. Valid QueryParamMatchType values, along with their +conformance levels, are: + +* "Exact" - Core +* "RegularExpression" - Implementation Specific + +Note that values may be added to this enum, implementations +must ensure that unknown values will not cause a crash. + +Unknown values here must result in the implementation setting the +Accepted Condition for the Route to `status: False`, with a +Reason of `UnsupportedValue`. + +_Validation:_ +- Enum: [Exact RegularExpression] + +_Appears in:_ +- [HTTPQueryParamMatch](#httpqueryparammatch) + +| Field | Description | +| --- | --- | +| `Exact` | | +| `RegularExpression` | | + + + + + + +#### RouteGroupKind + + + +RouteGroupKind indicates the group and kind of a Route resource. + + + +_Appears in:_ +- [AllowedRoutes](#allowedroutes) +- [ListenerStatus](#listenerstatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the Route. | gateway.networking.k8s.io | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is the kind of the Route. | | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| + + +#### RouteNamespaces + + + +RouteNamespaces indicate which namespaces Routes should be selected from. + + + +_Appears in:_ +- [AllowedRoutes](#allowedroutes) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `from` _[FromNamespaces](#fromnamespaces)_ | From indicates where Routes will be selected for this Gateway. Possible
values are:
* All: Routes in all namespaces may be used by this Gateway.
* Selector: Routes in namespaces selected by the selector may be used by
this Gateway.
* Same: Only Routes in the same namespace may be used by this Gateway.
Support: Core | Same | Enum: [All Selector Same]
| +| `selector` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#labelselector-v1-meta)_ | Selector must be specified when From is set to "Selector". In that case,
only Routes in Namespaces matching this Selector will be selected by this
Gateway. This field is ignored for other values of "From".
Support: Core | | | + + +#### RouteParentStatus + + + +RouteParentStatus describes the status of a route with respect to an +associated Parent. + + + +_Appears in:_ +- [GRPCRouteStatus](#grpcroutestatus) +- [HTTPRouteStatus](#httproutestatus) +- [RouteStatus](#routestatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `parentRef` _[ParentReference](#parentreference)_ | ParentRef corresponds with a ParentRef in the spec that this
RouteParentStatus struct describes the status of. | | | +| `controllerName` _[GatewayController](#gatewaycontroller)_ | ControllerName is a domain/path string that indicates the name of the
controller that wrote this status. This corresponds with the
controllerName field on GatewayClass.
Example: "example.net/gateway-controller".
The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are
valid Kubernetes names
(https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
Controllers MUST populate this field when writing status. Controllers should ensure that
entries to status populated with their ControllerName are cleaned up when they are no
longer necessary. | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$`
| +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#condition-v1-meta) array_ | Conditions describes the status of the route with respect to the Gateway.
Note that the route's availability is also subject to the Gateway's own
status conditions and listener status.
If the Route's ParentRef specifies an existing Gateway that supports
Routes of this kind AND that Gateway's controller has sufficient access,
then that Gateway's controller MUST set the "Accepted" condition on the
Route, to indicate whether the route has been accepted or rejected by the
Gateway, and why.
A Route MUST be considered "Accepted" if at least one of the Route's
rules is implemented by the Gateway.
There are a number of cases where the "Accepted" condition may not be set
due to lack of controller visibility, that includes when:
* The Route refers to a nonexistent parent.
* The Route is of a type that the controller does not support.
* The Route is in a namespace the controller does not have access to. | | MaxItems: 8
MinItems: 1
| + + +#### RouteStatus + + + +RouteStatus defines the common attributes that all Routes MUST include within +their status. + + + +_Appears in:_ +- [GRPCRouteStatus](#grpcroutestatus) +- [HTTPRouteStatus](#httproutestatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `parents` _[RouteParentStatus](#routeparentstatus) array_ | Parents is a list of parent resources (usually Gateways) that are
associated with the route, and the status of the route with respect to
each parent. When this route attaches to a parent, the controller that
manages the parent must add an entry to this list when the controller
first sees the route and should update the entry as appropriate when the
route or gateway is modified.
Note that parent references that cannot be resolved by an implementation
of this API will not be added to this list. Implementations of this API
can only populate Route status for the Gateways/parent resources they are
responsible for.
A maximum of 32 Gateways will be represented in this list. An empty list
means the route has not been attached to any Gateway. | | MaxItems: 32
| + + +#### SecretObjectReference + + + +SecretObjectReference identifies an API object including its namespace, +defaulting to Secret. + +The API object must be valid in the cluster; the Group and Kind must +be registered in the cluster for this reference to be valid. + +References to objects with invalid Group and Kind are not valid, and must +be rejected by the implementation, with appropriate Conditions set +on the containing object. + + + +_Appears in:_ +- [GatewayBackendTLS](#gatewaybackendtls) +- [GatewayTLSConfig](#gatewaytlsconfig) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent. For example, "gateway.networking.k8s.io".
When unspecified or empty string, core API group is inferred. | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is kind of the referent. For example "Secret". | Secret | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. | | MaxLength: 253
MinLength: 1
| +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referenced object. When unspecified, the local
namespace is inferred.
Note that when a namespace different than the local namespace is specified,
a ReferenceGrant object is required in the referent namespace to allow that
namespace's owner to accept the reference. See the ReferenceGrant
documentation for details.
Support: Core | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| + + +#### SectionName + +_Underlying type:_ _string_ + +SectionName is the name of a section in a Kubernetes resource. + +In the following resources, SectionName is interpreted as the following: + +* Gateway: Listener name +* HTTPRoute: HTTPRouteRule name +* Service: Port name + +Section names can have a variety of forms, including RFC 1123 subdomains, +RFC 1123 labels, or RFC 1035 labels. + +This validation is based off of the corresponding Kubernetes validation: +https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 + +Valid values include: + +* "example" +* "foo-example" +* "example.com" +* "foo.example.com" + +Invalid values include: + +* "example.com/bar" - "/" is an invalid character + +_Validation:_ +- MaxLength: 253 +- MinLength: 1 +- Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` + +_Appears in:_ +- [GRPCRouteRule](#grpcrouterule) +- [HTTPRouteRule](#httprouterule) +- [Listener](#listener) +- [ListenerStatus](#listenerstatus) +- [ParentReference](#parentreference) + + + +#### SessionPersistence + + + +SessionPersistence defines the desired state of SessionPersistence. + + + +_Appears in:_ +- [GRPCRouteRule](#grpcrouterule) +- [HTTPRouteRule](#httprouterule) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `sessionName` _string_ | SessionName defines the name of the persistent session token
which may be reflected in the cookie or the header. Users
should avoid reusing session names to prevent unintended
consequences, such as rejection or unpredictable behavior.
Support: Implementation-specific | | MaxLength: 128
| +| `absoluteTimeout` _[Duration](#duration)_ | AbsoluteTimeout defines the absolute timeout of the persistent
session. Once the AbsoluteTimeout duration has elapsed, the
session becomes invalid.
Support: Extended | | Pattern: `^([0-9]\{1,5\}(h\|m\|s\|ms))\{1,4\}$`
| +| `idleTimeout` _[Duration](#duration)_ | IdleTimeout defines the idle timeout of the persistent session.
Once the session has been idle for more than the specified
IdleTimeout duration, the session becomes invalid.
Support: Extended | | Pattern: `^([0-9]\{1,5\}(h\|m\|s\|ms))\{1,4\}$`
| +| `type` _[SessionPersistenceType](#sessionpersistencetype)_ | Type defines the type of session persistence such as through
the use a header or cookie. Defaults to cookie based session
persistence.
Support: Core for "Cookie" type
Support: Extended for "Header" type | Cookie | Enum: [Cookie Header]
| +| `cookieConfig` _[CookieConfig](#cookieconfig)_ | CookieConfig provides configuration settings that are specific
to cookie-based session persistence.
Support: Core | | | + + +#### SessionPersistenceType + +_Underlying type:_ _string_ + + + +_Validation:_ +- Enum: [Cookie Header] + +_Appears in:_ +- [SessionPersistence](#sessionpersistence) + +| Field | Description | +| --- | --- | +| `Cookie` | CookieBasedSessionPersistence specifies cookie-based session
persistence.
Support: Core
| +| `Header` | HeaderBasedSessionPersistence specifies header-based session
persistence.
Support: Extended
| + + +#### SupportedFeature + + + + + + + +_Appears in:_ +- [GatewayClassStatus](#gatewayclassstatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _[FeatureName](#featurename)_ | | | | + + +#### TLSModeType + +_Underlying type:_ _string_ + +TLSModeType type defines how a Gateway handles TLS sessions. + +_Validation:_ +- Enum: [Terminate Passthrough] + +_Appears in:_ +- [GatewayTLSConfig](#gatewaytlsconfig) + +| Field | Description | +| --- | --- | +| `Terminate` | In this mode, TLS session between the downstream client
and the Gateway is terminated at the Gateway.
| +| `Passthrough` | In this mode, the TLS session is NOT terminated by the Gateway. This
implies that the Gateway can't decipher the TLS stream except for
the ClientHello message of the TLS protocol.
Note that SSL passthrough is only supported by TLSRoute.
| + + +#### TrueField + +_Underlying type:_ _boolean_ + +TrueField is a boolean value that can only be set to true + +_Validation:_ +- Enum: [true] + +_Appears in:_ +- [HTTPCORSFilter](#httpcorsfilter) + + + + +## gateway.networking.k8s.io/v1alpha2 + +Package v1alpha2 contains API Schema definitions for the +gateway.networking.k8s.io API group. + + +### Resource Types +- [GRPCRoute](#grpcroute) +- [ReferenceGrant](#referencegrant) +- [TCPRoute](#tcproute) +- [TLSRoute](#tlsroute) +- [UDPRoute](#udproute) + + + + + + + + + + + + + + + + + +#### GRPCRoute + +_Underlying type:_ _[GRPCRoute](#grpcroute)_ + + + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1alpha2` | | | +| `kind` _string_ | `GRPCRoute` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[GRPCRouteSpec](#grpcroutespec)_ | Spec defines the desired state of GRPCRoute. | | | +| `status` _[GRPCRouteStatus](#grpcroutestatus)_ | Status defines the current state of GRPCRoute. | | | + + + + + + + + + + + + +#### LocalPolicyTargetReference + + + +LocalPolicyTargetReference identifies an API object to apply a direct or +inherited policy to. This should be used as part of Policy resources +that can target Gateway API resources. For more information on how this +policy attachment model works, and a sample Policy resource, refer to +the policy attachment documentation for Gateway API. + + + +_Appears in:_ +- [LocalPolicyTargetReferenceWithSectionName](#localpolicytargetreferencewithsectionname) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the target resource. | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is kind of the target resource. | | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the target resource. | | MaxLength: 253
MinLength: 1
| + + +#### LocalPolicyTargetReferenceWithSectionName + + + +LocalPolicyTargetReferenceWithSectionName identifies an API object to apply a +direct policy to. This should be used as part of Policy resources that can +target single resources. For more information on how this policy attachment +mode works, and a sample Policy resource, refer to the policy attachment +documentation for Gateway API. + +Note: This should only be used for direct policy attachment when references +to SectionName are actually needed. In all other cases, +LocalPolicyTargetReference should be used. + + + +_Appears in:_ +- [BackendTLSPolicySpec](#backendtlspolicyspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the target resource. | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is kind of the target resource. | | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the target resource. | | MaxLength: 253
MinLength: 1
| +| `sectionName` _[SectionName](#sectionname)_ | SectionName is the name of a section within the target resource. When
unspecified, this targetRef targets the entire resource. In the following
resources, SectionName is interpreted as the following:
* Gateway: Listener name
* HTTPRoute: HTTPRouteRule name
* Service: Port name
If a SectionName is specified, but does not exist on the targeted object,
the Policy must fail to attach, and the policy implementation should record
a `ResolvedRefs` or similar Condition in the Policy's status. | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| + + + + + + + + + + +#### PolicyAncestorStatus + + + +PolicyAncestorStatus describes the status of a route with respect to an +associated Ancestor. + +Ancestors refer to objects that are either the Target of a policy or above it +in terms of object hierarchy. For example, if a policy targets a Service, the +Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and +the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most +useful object to place Policy status on, so we recommend that implementations +SHOULD use Gateway as the PolicyAncestorStatus object unless the designers +have a _very_ good reason otherwise. + +In the context of policy attachment, the Ancestor is used to distinguish which +resource results in a distinct application of this policy. For example, if a policy +targets a Service, it may have a distinct result per attached Gateway. + +Policies targeting the same resource may have different effects depending on the +ancestors of those resources. For example, different Gateways targeting the same +Service may have different capabilities, especially if they have different underlying +implementations. + +For example, in BackendTLSPolicy, the Policy attaches to a Service that is +used as a backend in a HTTPRoute that is itself attached to a Gateway. +In this case, the relevant object for status is the Gateway, and that is the +ancestor object referred to in this status. + +Note that a parent is also an ancestor, so for objects where the parent is the +relevant object for status, this struct SHOULD still be used. + +This struct is intended to be used in a slice that's effectively a map, +with a composite key made up of the AncestorRef and the ControllerName. + + + +_Appears in:_ +- [PolicyStatus](#policystatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `ancestorRef` _[ParentReference](#parentreference)_ | AncestorRef corresponds with a ParentRef in the spec that this
PolicyAncestorStatus struct describes the status of. | | | +| `controllerName` _[GatewayController](#gatewaycontroller)_ | ControllerName is a domain/path string that indicates the name of the
controller that wrote this status. This corresponds with the
controllerName field on GatewayClass.
Example: "example.net/gateway-controller".
The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are
valid Kubernetes names
(https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names).
Controllers MUST populate this field when writing status. Controllers should ensure that
entries to status populated with their ControllerName are cleaned up when they are no
longer necessary. | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$`
| +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#condition-v1-meta) array_ | Conditions describes the status of the Policy with respect to the given Ancestor. | | MaxItems: 8
MinItems: 1
| + + + + + + +#### PolicyStatus + + + +PolicyStatus defines the common attributes that all Policies should include within +their status. + + + +_Appears in:_ +- [BackendTLSPolicy](#backendtlspolicy) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `ancestors` _[PolicyAncestorStatus](#policyancestorstatus) array_ | Ancestors is a list of ancestor resources (usually Gateways) that are
associated with the policy, and the status of the policy with respect to
each ancestor. When this policy attaches to a parent, the controller that
manages the parent and the ancestors MUST add an entry to this list when
the controller first sees the policy and SHOULD update the entry as
appropriate when the relevant ancestor is modified.
Note that choosing the relevant ancestor is left to the Policy designers;
an important part of Policy design is designing the right object level at
which to namespace this status.
Note also that implementations MUST ONLY populate ancestor status for
the Ancestor resources they are responsible for. Implementations MUST
use the ControllerName field to uniquely identify the entries in this list
that they are responsible for.
Note that to achieve this, the list of PolicyAncestorStatus structs
MUST be treated as a map with a composite key, made up of the AncestorRef
and ControllerName fields combined.
A maximum of 16 ancestors will be represented in this list. An empty list
means the Policy is not relevant for any ancestors.
If this slice is full, implementations MUST NOT add further entries.
Instead they MUST consider the policy unimplementable and signal that
on any related resources such as the ancestor that would be referenced
here. For example, if this list was full on BackendTLSPolicy, no
additional Gateways would be able to reference the Service targeted by
the BackendTLSPolicy. | | MaxItems: 16
| + + + + + + +#### ReferenceGrant + +_Underlying type:_ _[ReferenceGrant](#referencegrant)_ + +ReferenceGrant identifies kinds of resources in other namespaces that are +trusted to reference the specified kinds of resources in the same namespace +as the policy. + +Each ReferenceGrant can be used to represent a unique trust relationship. +Additional Reference Grants can be used to add to the set of trusted +sources of inbound references for the namespace they are defined within. + +A ReferenceGrant is required for all cross-namespace references in Gateway API +(with the exception of cross-namespace Route-Gateway attachment, which is +governed by the AllowedRoutes configuration on the Gateway, and cross-namespace +Service ParentRefs on a "consumer" mesh Route, which defines routing rules +applicable only to workloads in the Route namespace). ReferenceGrants allowing +a reference from a Route to a Service are only applicable to BackendRefs. + +ReferenceGrant is a form of runtime verification allowing users to assert +which cross-namespace object references are permitted. Implementations that +support ReferenceGrant MUST NOT permit cross-namespace references which have +no grant, and MUST respond to the removal of a grant by revoking the access +that the grant allowed. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1alpha2` | | | +| `kind` _string_ | `ReferenceGrant` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[ReferenceGrantSpec](#referencegrantspec)_ | Spec defines the desired state of ReferenceGrant. | | | + + + + + + + + + + + + + + + + + + + + + + +#### TCPRoute + + + +TCPRoute provides a way to route TCP requests. When combined with a Gateway +listener, it can be used to forward connections on the port specified by the +listener to a set of backends specified by the TCPRoute. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1alpha2` | | | +| `kind` _string_ | `TCPRoute` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[TCPRouteSpec](#tcproutespec)_ | Spec defines the desired state of TCPRoute. | | | +| `status` _[TCPRouteStatus](#tcproutestatus)_ | Status defines the current state of TCPRoute. | | | + + +#### TCPRouteRule + + + +TCPRouteRule is the configuration for a given rule. + + + +_Appears in:_ +- [TCPRouteSpec](#tcproutespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _[SectionName](#sectionname)_ | Name is the name of the route rule. This name MUST be unique within a Route if it is set.
Support: Extended | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `backendRefs` _[BackendRef](#backendref) array_ | BackendRefs defines the backend(s) where matching requests should be
sent. If unspecified or invalid (refers to a nonexistent resource or a
Service with no endpoints), the underlying implementation MUST actively
reject connection attempts to this backend. Connection rejections must
respect weight; if an invalid backend is requested to have 80% of
connections, then 80% of connections must be rejected instead.
Support: Core for Kubernetes Service
Support: Extended for Kubernetes ServiceImport
Support: Implementation-specific for any other resource
Support for weight: Extended | | MaxItems: 16
MinItems: 1
| + + +#### TCPRouteSpec + + + +TCPRouteSpec defines the desired state of TCPRoute + + + +_Appears in:_ +- [TCPRoute](#tcproute) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `rules` _[TCPRouteRule](#tcprouterule) array_ | Rules are a list of TCP matchers and actions.
| | MaxItems: 16
MinItems: 1
| + + +#### TCPRouteStatus + + + +TCPRouteStatus defines the observed state of TCPRoute + + + +_Appears in:_ +- [TCPRoute](#tcproute) + + + +#### TLSRoute + + + +The TLSRoute resource is similar to TCPRoute, but can be configured +to match against TLS-specific metadata. This allows more flexibility +in matching streams for a given TLS listener. + +If you need to forward traffic to a single target for a TLS listener, you +could choose to use a TCPRoute with a TLS listener. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1alpha2` | | | +| `kind` _string_ | `TLSRoute` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[TLSRouteSpec](#tlsroutespec)_ | Spec defines the desired state of TLSRoute. | | | +| `status` _[TLSRouteStatus](#tlsroutestatus)_ | Status defines the current state of TLSRoute. | | | + + +#### TLSRouteRule + + + +TLSRouteRule is the configuration for a given rule. + + + +_Appears in:_ +- [TLSRouteSpec](#tlsroutespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _[SectionName](#sectionname)_ | Name is the name of the route rule. This name MUST be unique within a Route if it is set.
Support: Extended | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `backendRefs` _[BackendRef](#backendref) array_ | BackendRefs defines the backend(s) where matching requests should be
sent. If unspecified or invalid (refers to a nonexistent resource or
a Service with no endpoints), the rule performs no forwarding; if no
filters are specified that would result in a response being sent, the
underlying implementation must actively reject request attempts to this
backend, by rejecting the connection or returning a 500 status code.
Request rejections must respect weight; if an invalid backend is
requested to have 80% of requests, then 80% of requests must be rejected
instead.
Support: Core for Kubernetes Service
Support: Extended for Kubernetes ServiceImport
Support: Implementation-specific for any other resource
Support for weight: Extended | | MaxItems: 16
MinItems: 1
| + + +#### TLSRouteSpec + + + +TLSRouteSpec defines the desired state of a TLSRoute resource. + + + +_Appears in:_ +- [TLSRoute](#tlsroute) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `hostnames` _[Hostname](#hostname) array_ | Hostnames defines a set of SNI names that should match against the
SNI attribute of TLS ClientHello message in TLS handshake. This matches
the RFC 1123 definition of a hostname with 2 notable exceptions:
1. IPs are not allowed in SNI names per RFC 6066.
2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard
label must appear by itself as the first label.
If a hostname is specified by both the Listener and TLSRoute, there
must be at least one intersecting hostname for the TLSRoute to be
attached to the Listener. For example:
* A Listener with `test.example.com` as the hostname matches TLSRoutes
that have either not specified any hostnames, or have specified at
least one of `test.example.com` or `*.example.com`.
* A Listener with `*.example.com` as the hostname matches TLSRoutes
that have either not specified any hostnames or have specified at least
one hostname that matches the Listener hostname. For example,
`test.example.com` and `*.example.com` would both match. On the other
hand, `example.com` and `test.example.net` would not match.
If both the Listener and TLSRoute have specified hostnames, any
TLSRoute hostnames that do not match the Listener hostname MUST be
ignored. For example, if a Listener specified `*.example.com`, and the
TLSRoute specified `test.example.com` and `test.example.net`,
`test.example.net` must not be considered for a match.
If both the Listener and TLSRoute have specified hostnames, and none
match with the criteria above, then the TLSRoute is not accepted. The
implementation must raise an 'Accepted' Condition with a status of
`False` in the corresponding RouteParentStatus.
Support: Core | | MaxItems: 16
MaxLength: 253
MinLength: 1
Pattern: `^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `rules` _[TLSRouteRule](#tlsrouterule) array_ | Rules are a list of TLS matchers and actions.
| | MaxItems: 16
MinItems: 1
| + + +#### TLSRouteStatus + + + +TLSRouteStatus defines the observed state of TLSRoute + + + +_Appears in:_ +- [TLSRoute](#tlsroute) + + + +#### UDPRoute + + + +UDPRoute provides a way to route UDP traffic. When combined with a Gateway +listener, it can be used to forward traffic on the port specified by the +listener to a set of backends specified by the UDPRoute. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1alpha2` | | | +| `kind` _string_ | `UDPRoute` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[UDPRouteSpec](#udproutespec)_ | Spec defines the desired state of UDPRoute. | | | +| `status` _[UDPRouteStatus](#udproutestatus)_ | Status defines the current state of UDPRoute. | | | + + +#### UDPRouteRule + + + +UDPRouteRule is the configuration for a given rule. + + + +_Appears in:_ +- [UDPRouteSpec](#udproutespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _[SectionName](#sectionname)_ | Name is the name of the route rule. This name MUST be unique within a Route if it is set.
Support: Extended | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `backendRefs` _[BackendRef](#backendref) array_ | BackendRefs defines the backend(s) where matching requests should be
sent. If unspecified or invalid (refers to a nonexistent resource or a
Service with no endpoints), the underlying implementation MUST actively
reject connection attempts to this backend. Packet drops must
respect weight; if an invalid backend is requested to have 80% of
the packets, then 80% of packets must be dropped instead.
Support: Core for Kubernetes Service
Support: Extended for Kubernetes ServiceImport
Support: Implementation-specific for any other resource
Support for weight: Extended | | MaxItems: 16
MinItems: 1
| + + +#### UDPRouteSpec + + + +UDPRouteSpec defines the desired state of UDPRoute. + + + +_Appears in:_ +- [UDPRoute](#udproute) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `rules` _[UDPRouteRule](#udprouterule) array_ | Rules are a list of UDP matchers and actions.
| | MaxItems: 16
MinItems: 1
| + + +#### UDPRouteStatus + + + +UDPRouteStatus defines the observed state of UDPRoute. + + + +_Appears in:_ +- [UDPRoute](#udproute) + + + + +## gateway.networking.k8s.io/v1alpha3 + +Package v1alpha3 contains API Schema definitions for the +gateway.networking.k8s.io API group. + + +### Resource Types +- [BackendTLSPolicy](#backendtlspolicy) + + + +#### BackendTLSPolicy + + + +BackendTLSPolicy provides a way to configure how a Gateway +connects to a Backend via TLS. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1alpha3` | | | +| `kind` _string_ | `BackendTLSPolicy` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[BackendTLSPolicySpec](#backendtlspolicyspec)_ | Spec defines the desired state of BackendTLSPolicy. | | | +| `status` _[PolicyStatus](#policystatus)_ | Status defines the current state of BackendTLSPolicy. | | | + + +#### BackendTLSPolicySpec + + + +BackendTLSPolicySpec defines the desired state of BackendTLSPolicy. + +Support: Extended + + + +_Appears in:_ +- [BackendTLSPolicy](#backendtlspolicy) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `targetRefs` _[LocalPolicyTargetReferenceWithSectionName](#localpolicytargetreferencewithsectionname) array_ | TargetRefs identifies an API object to apply the policy to.
Only Services have Extended support. Implementations MAY support
additional objects, with Implementation Specific support.
Note that this config applies to the entire referenced resource
by default, but this default may change in the future to provide
a more granular application of the policy.
TargetRefs must be _distinct_. This means either that:
* They select different targets. If this is the case, then targetRef
entries are distinct. In terms of fields, this means that the
multi-part key defined by `group`, `kind`, and `name` must
be unique across all targetRef entries in the BackendTLSPolicy.
* They select different sectionNames in the same target.
Support: Extended for Kubernetes Service
Support: Implementation-specific for any other resource | | MaxItems: 16
MinItems: 1
| +| `validation` _[BackendTLSPolicyValidation](#backendtlspolicyvalidation)_ | Validation contains backend TLS validation configuration. | | | +| `options` _object (keys:[AnnotationKey](#annotationkey), values:[AnnotationValue](#annotationvalue))_ | Options are a list of key/value pairs to enable extended TLS
configuration for each implementation. For example, configuring the
minimum TLS version or supported cipher suites.
A set of common keys MAY be defined by the API in the future. To avoid
any ambiguity, implementation-specific definitions MUST use
domain-prefixed names, such as `example.com/my-custom-option`.
Un-prefixed names are reserved for key names defined by Gateway API.
Support: Implementation-specific | | MaxProperties: 16
| + + +#### BackendTLSPolicyValidation + + + +BackendTLSPolicyValidation contains backend TLS validation configuration. + + + +_Appears in:_ +- [BackendTLSPolicySpec](#backendtlspolicyspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `caCertificateRefs` _[LocalObjectReference](#localobjectreference) array_ | CACertificateRefs contains one or more references to Kubernetes objects that
contain a PEM-encoded TLS CA certificate bundle, which is used to
validate a TLS handshake between the Gateway and backend Pod.
If CACertificateRefs is empty or unspecified, then WellKnownCACertificates must be
specified. Only one of CACertificateRefs or WellKnownCACertificates may be specified,
not both. If CACertificateRefs is empty or unspecified, the configuration for
WellKnownCACertificates MUST be honored instead if supported by the implementation.
References to a resource in a different namespace are invalid for the
moment, although we will revisit this in the future.
A single CACertificateRef to a Kubernetes ConfigMap kind has "Core" support.
Implementations MAY choose to support attaching multiple certificates to
a backend, but this behavior is implementation-specific.
Support: Core - An optional single reference to a Kubernetes ConfigMap,
with the CA certificate in a key named `ca.crt`.
Support: Implementation-specific (More than one reference, or other kinds
of resources). | | MaxItems: 8
| +| `wellKnownCACertificates` _[WellKnownCACertificatesType](#wellknowncacertificatestype)_ | WellKnownCACertificates specifies whether system CA certificates may be used in
the TLS handshake between the gateway and backend pod.
If WellKnownCACertificates is unspecified or empty (""), then CACertificateRefs
must be specified with at least one entry for a valid configuration. Only one of
CACertificateRefs or WellKnownCACertificates may be specified, not both. If an
implementation does not support the WellKnownCACertificates field or the value
supplied is not supported, the Status Conditions on the Policy MUST be
updated to include an Accepted: False Condition with Reason: Invalid.
Support: Implementation-specific | | Enum: [System]
| +| `hostname` _[PreciseHostname](#precisehostname)_ | Hostname is used for two purposes in the connection between Gateways and
backends:
1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066).
2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend, unless SubjectAltNames is specified.
authentication and MUST match the certificate served by the matching
backend.
Support: Core | | MaxLength: 253
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `subjectAltNames` _[SubjectAltName](#subjectaltname) array_ | SubjectAltNames contains one or more Subject Alternative Names.
When specified the certificate served from the backend MUST
have at least one Subject Alternate Name matching one of the specified SubjectAltNames.
Support: Extended | | MaxItems: 5
| + + +#### SubjectAltName + + + +SubjectAltName represents Subject Alternative Name. + + + +_Appears in:_ +- [BackendTLSPolicyValidation](#backendtlspolicyvalidation) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[SubjectAltNameType](#subjectaltnametype)_ | Type determines the format of the Subject Alternative Name. Always required.
Support: Core | | Enum: [Hostname URI]
| +| `hostname` _[Hostname](#hostname)_ | Hostname contains Subject Alternative Name specified in DNS name format.
Required when Type is set to Hostname, ignored otherwise.
Support: Core | | MaxLength: 253
MinLength: 1
Pattern: `^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `uri` _[AbsoluteURI](#absoluteuri)_ | URI contains Subject Alternative Name specified in a full URI format.
It MUST include both a scheme (e.g., "http" or "ftp") and a scheme-specific-part.
Common values include SPIFFE IDs like "spiffe://mycluster.example.com/ns/myns/sa/svc1sa".
Required when Type is set to URI, ignored otherwise.
Support: Core | | MaxLength: 253
MinLength: 1
Pattern: `^(([^:/?#]+):)(//([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?`
| + + +#### SubjectAltNameType + +_Underlying type:_ _string_ + +SubjectAltNameType is the type of the Subject Alternative Name. + +_Validation:_ +- Enum: [Hostname URI] + +_Appears in:_ +- [SubjectAltName](#subjectaltname) + +| Field | Description | +| --- | --- | +| `Hostname` | HostnameSubjectAltNameType specifies hostname-based SAN.
Support: Core
| +| `URI` | URISubjectAltNameType specifies URI-based SAN, e.g. SPIFFE id.
Support: Core
| + + +#### WellKnownCACertificatesType + +_Underlying type:_ _string_ + +WellKnownCACertificatesType is the type of CA certificate that will be used +when the caCertificateRefs field is unspecified. + +_Validation:_ +- Enum: [System] + +_Appears in:_ +- [BackendTLSPolicyValidation](#backendtlspolicyvalidation) + +| Field | Description | +| --- | --- | +| `System` | WellKnownCACertificatesSystem indicates that well known system CA certificates should be used.
| + + + +## gateway.networking.k8s.io/v1beta1 + +Package v1beta1 contains API Schema definitions for the +gateway.networking.k8s.io API group. + + +### Resource Types +- [Gateway](#gateway) +- [GatewayClass](#gatewayclass) +- [HTTPRoute](#httproute) +- [ReferenceGrant](#referencegrant) + + + + + + + + + + + + + + + + + + + + + +#### Gateway + +_Underlying type:_ _[Gateway](#gateway)_ + +Gateway represents an instance of a service-traffic handling infrastructure +by binding Listeners to a set of IP addresses. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1beta1` | | | +| `kind` _string_ | `Gateway` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[GatewaySpec](#gatewayspec)_ | Spec defines the desired state of Gateway. | | | +| `status` _[GatewayStatus](#gatewaystatus)_ | Status defines the current state of Gateway. | \{ conditions:[map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted] map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Programmed]] \} | | + + +#### GatewayClass + +_Underlying type:_ _[GatewayClass](#gatewayclass)_ + +GatewayClass describes a class of Gateways available to the user for creating +Gateway resources. + +It is recommended that this resource be used as a template for Gateways. This +means that a Gateway is based on the state of the GatewayClass at the time it +was created and changes to the GatewayClass or associated parameters are not +propagated down to existing Gateways. This recommendation is intended to +limit the blast radius of changes to GatewayClass or associated parameters. +If implementations choose to propagate GatewayClass changes to existing +Gateways, that MUST be clearly documented by the implementation. + +Whenever one or more Gateways are using a GatewayClass, implementations SHOULD +add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the +associated GatewayClass. This ensures that a GatewayClass associated with a +Gateway is not deleted while in use. + +GatewayClass is a Cluster level resource. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1beta1` | | | +| `kind` _string_ | `GatewayClass` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[GatewayClassSpec](#gatewayclassspec)_ | Spec defines the desired state of GatewayClass. | | | +| `status` _[GatewayClassStatus](#gatewayclassstatus)_ | Status defines the current state of GatewayClass.
Implementations MUST populate status on all GatewayClass resources which
specify their controller name. | \{ conditions:[map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted]] \} | | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#### HTTPRoute + +_Underlying type:_ _[HTTPRoute](#httproute)_ + +HTTPRoute provides a way to route HTTP requests. This includes the capability +to match requests by hostname, path, header, or query param. Filters can be +used to specify additional processing steps. Backends specify where matching +requests should be routed. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1beta1` | | | +| `kind` _string_ | `HTTPRoute` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[HTTPRouteSpec](#httproutespec)_ | Spec defines the desired state of HTTPRoute. | | | +| `status` _[HTTPRouteStatus](#httproutestatus)_ | Status defines the current state of HTTPRoute. | | | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#### ReferenceGrant + + + +ReferenceGrant identifies kinds of resources in other namespaces that are +trusted to reference the specified kinds of resources in the same namespace +as the policy. + +Each ReferenceGrant can be used to represent a unique trust relationship. +Additional Reference Grants can be used to add to the set of trusted +sources of inbound references for the namespace they are defined within. + +All cross-namespace references in Gateway API (with the exception of cross-namespace +Gateway-route attachment) require a ReferenceGrant. + +ReferenceGrant is a form of runtime verification allowing users to assert +which cross-namespace object references are permitted. Implementations that +support ReferenceGrant MUST NOT permit cross-namespace references which have +no grant, and MUST respond to the removal of a grant by revoking the access +that the grant allowed. + + + +_Appears in:_ +- [ReferenceGrant](#referencegrant) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.k8s.io/v1beta1` | | | +| `kind` _string_ | `ReferenceGrant` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[ReferenceGrantSpec](#referencegrantspec)_ | Spec defines the desired state of ReferenceGrant. | | | + + +#### ReferenceGrantFrom + + + +ReferenceGrantFrom describes trusted namespaces and kinds. + + + +_Appears in:_ +- [ReferenceGrantSpec](#referencegrantspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent.
When empty, the Kubernetes core API group is inferred.
Support: Core | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is the kind of the referent. Although implementations may support
additional resources, the following types are part of the "Core"
support level for this field.
When used to permit a SecretObjectReference:
* Gateway
When used to permit a BackendObjectReference:
* GRPCRoute
* HTTPRoute
* TCPRoute
* TLSRoute
* UDPRoute | | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referent.
Support: Core | | MaxLength: 63
MinLength: 1
Pattern: `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
| + + +#### ReferenceGrantSpec + + + +ReferenceGrantSpec identifies a cross namespace relationship that is trusted +for Gateway API. + + + +_Appears in:_ +- [ReferenceGrant](#referencegrant) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `from` _[ReferenceGrantFrom](#referencegrantfrom) array_ | From describes the trusted namespaces and kinds that can reference the
resources described in "To". Each entry in this list MUST be considered
to be an additional place that references can be valid from, or to put
this another way, entries MUST be combined using OR.
Support: Core | | MaxItems: 16
MinItems: 1
| +| `to` _[ReferenceGrantTo](#referencegrantto) array_ | To describes the resources that may be referenced by the resources
described in "From". Each entry in this list MUST be considered to be an
additional place that references can be valid to, or to put this another
way, entries MUST be combined using OR.
Support: Core | | MaxItems: 16
MinItems: 1
| + + +#### ReferenceGrantTo + + + +ReferenceGrantTo describes what Kinds are allowed as targets of the +references. + + + +_Appears in:_ +- [ReferenceGrantSpec](#referencegrantspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent.
When empty, the Kubernetes core API group is inferred.
Support: Core | | MaxLength: 253
Pattern: `^$\|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
| +| `kind` _[Kind](#kind)_ | Kind is the kind of the referent. Although implementations may support
additional resources, the following types are part of the "Core"
support level for this field:
* Secret when used to permit a SecretObjectReference
* Service when used to permit a BackendObjectReference | | MaxLength: 63
MinLength: 1
Pattern: `^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$`
| +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. When unspecified, this policy
refers to all resources of the specified Group and Kind in the local
namespace. | | MaxLength: 253
MinLength: 1
| + + + + + + + + + + + + + + + + + + + + diff --git a/site-src/ko/reference/specx.md b/site-src/ko/reference/specx.md new file mode 100644 index 0000000000..d234d9750f --- /dev/null +++ b/site-src/ko/reference/specx.md @@ -0,0 +1,263 @@ +# API Reference + +## Packages +- [gateway.networking.x-k8s.io/v1alpha1](#gatewaynetworkingx-k8siov1alpha1) + + +## gateway.networking.x-k8s.io/v1alpha1 + +Package v1alpha1 contains API Schema definitions for the gateway.networking.k8s-x.io +API group. + + +### Resource Types +- [XBackendTrafficPolicy](#xbackendtrafficpolicy) +- [XListenerSet](#xlistenerset) + + + + + +#### BackendTrafficPolicySpec + + + +BackendTrafficPolicySpec define the desired state of BackendTrafficPolicy +Note: there is no Override or Default policy configuration. + + + +_Appears in:_ +- [XBackendTrafficPolicy](#xbackendtrafficpolicy) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `targetRefs` _[LocalPolicyTargetReference](#localpolicytargetreference) array_ | TargetRefs identifies API object(s) to apply this policy to.
Currently, Backends (A grouping of like endpoints such as Service,
ServiceImport, or any implementation-specific backendRef) are the only
valid API target references.
Currently, a TargetRef can not be scoped to a specific port on a
Service. | | MaxItems: 16
MinItems: 1
| +| `retryConstraint` _[RetryConstraint](#retryconstraint)_ | RetryConstraint defines the configuration for when to allow or prevent
further retries to a target backend, by dynamically calculating a 'retry
budget'. This budget is calculated based on the percentage of incoming
traffic composed of retries over a given time interval. Once the budget
is exceeded, additional retries will be rejected.
For example, if the retry budget interval is 10 seconds, there have been
1000 active requests in the past 10 seconds, and the allowed percentage
of requests that can be retried is 20% (the default), then 200 of those
requests may be composed of retries. Active requests will only be
considered for the duration of the interval when calculating the retry
budget. Retrying the same original request multiple times within the
retry budget interval will lead to each retry being counted towards
calculating the budget.
Configuring a RetryConstraint in BackendTrafficPolicy is compatible with
HTTPRoute Retry settings for each HTTPRouteRule that targets the same
backend. While the HTTPRouteRule Retry stanza can specify whether a
request will be retried, and the number of retry attempts each client
may perform, RetryConstraint helps prevent cascading failures such as
retry storms during periods of consistent failures.
After the retry budget has been exceeded, additional retries to the
backend MUST return a 503 response to the client.
Additional configurations for defining a constraint on retries MAY be
defined in the future.
Support: Extended
| | | +| `sessionPersistence` _[SessionPersistence](#sessionpersistence)_ | SessionPersistence defines and configures session persistence
for the backend.
Support: Extended | | | + + +#### BudgetDetails + + + +BudgetDetails specifies the details of the budget configuration, like +the percentage of requests in the budget, and the interval between +checks. + + + +_Appears in:_ +- [RetryConstraint](#retryconstraint) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `percent` _integer_ | BudgetPercent defines the maximum percentage of active requests that may
be made up of retries.
Support: Extended | 20 | Maximum: 100
Minimum: 0
| +| `interval` _[Duration](#duration)_ | BudgetInterval defines the duration in which requests will be considered
for calculating the budget for retries.
Support: Extended | 10s | | + + + + + + + + + + + + +#### ListenerEntry + + + + + + + +_Appears in:_ +- [ListenerSetSpec](#listenersetspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _[SectionName](#sectionname)_ | Name is the name of the Listener. This name MUST be unique within a
ListenerSet.
Name is not required to be unique across a Gateway and ListenerSets.
Routes can attach to a Listener by having a ListenerSet as a parentRef
and setting the SectionName | | | +| `hostname` _[Hostname](#hostname)_ | Hostname specifies the virtual hostname to match for protocol types that
define this concept. When unspecified, all hostnames are matched. This
field is ignored for protocols that don't require hostname based
matching.
Implementations MUST apply Hostname matching appropriately for each of
the following protocols:
* TLS: The Listener Hostname MUST match the SNI.
* HTTP: The Listener Hostname MUST match the Host header of the request.
* HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP
protocol layers as described above. If an implementation does not
ensure that both the SNI and Host header match the Listener hostname,
it MUST clearly document that.
For HTTPRoute and TLSRoute resources, there is an interaction with the
`spec.hostnames` array. When both listener and route specify hostnames,
there MUST be an intersection between the values for a Route to be
accepted. For more information, refer to the Route specific Hostnames
documentation.
Hostnames that are prefixed with a wildcard label (`*.`) are interpreted
as a suffix match. That means that a match for `*.example.com` would match
both `test.example.com`, and `foo.test.example.com`, but not `example.com`. | | | +| `port` _[PortNumber](#portnumber)_ | Port is the network port. Multiple listeners may use the
same port, subject to the Listener compatibility rules. | | | +| `protocol` _[ProtocolType](#protocoltype)_ | Protocol specifies the network protocol this listener expects to receive. | | | +| `tls` _[GatewayTLSConfig](#gatewaytlsconfig)_ | TLS is the TLS configuration for the Listener. This field is required if
the Protocol field is "HTTPS" or "TLS". It is invalid to set this field
if the Protocol field is "HTTP", "TCP", or "UDP".
The association of SNIs to Certificate defined in GatewayTLSConfig is
defined based on the Hostname field for this listener.
The GatewayClass MUST use the longest matching SNI out of all
available certificates for any TLS handshake. | | | +| `allowedRoutes` _[AllowedRoutes](#allowedroutes)_ | AllowedRoutes defines the types of routes that MAY be attached to a
Listener and the trusted namespaces where those Route resources MAY be
present.
Although a client request may match multiple route rules, only one rule
may ultimately receive the request. Matching precedence MUST be
determined in order of the following criteria:
* The most specific match as defined by the Route type.
* The oldest Route based on creation timestamp. For example, a Route with
a creation timestamp of "2020-09-08 01:02:03" is given precedence over
a Route with a creation timestamp of "2020-09-08 01:02:04".
* If everything else is equivalent, the Route appearing first in
alphabetical order (namespace/name) should be given precedence. For
example, foo/bar is given precedence over foo/baz.
All valid rules within a Route attached to this Listener should be
implemented. Invalid Route rules can be ignored (sometimes that will mean
the full Route). If a Route rule transitions from valid to invalid,
support for that Route rule should be dropped to ensure consistency. For
example, even if a filter specified by a Route rule is invalid, the rest
of the rules within that Route should still be supported. | \{ namespaces:map[from:Same] \} | | + + + + + + +#### ListenerEntryStatus + + + +ListenerStatus is the status associated with a Listener. + + + +_Appears in:_ +- [ListenerSetStatus](#listenersetstatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _[SectionName](#sectionname)_ | Name is the name of the Listener that this status corresponds to. | | | +| `port` _[PortNumber](#portnumber)_ | Port is the network port the listener is configured to listen on. | | | +| `supportedKinds` _[RouteGroupKind](#routegroupkind) array_ | SupportedKinds is the list indicating the Kinds supported by this
listener. This MUST represent the kinds an implementation supports for
that Listener configuration.
If kinds are specified in Spec that are not supported, they MUST NOT
appear in this list and an implementation MUST set the "ResolvedRefs"
condition to "False" with the "InvalidRouteKinds" reason. If both valid
and invalid Route kinds are specified, the implementation MUST
reference the valid Route kinds that have been specified. | | MaxItems: 8
| +| `attachedRoutes` _integer_ | AttachedRoutes represents the total number of Routes that have been
successfully attached to this Listener.
Successful attachment of a Route to a Listener is based solely on the
combination of the AllowedRoutes field on the corresponding Listener
and the Route's ParentRefs field. A Route is successfully attached to
a Listener when it is selected by the Listener's AllowedRoutes field
AND the Route has a valid ParentRef selecting the whole Gateway
resource or a specific Listener as a parent resource (more detail on
attachment semantics can be found in the documentation on the various
Route kinds ParentRefs fields). Listener or Route status does not impact
successful attachment, i.e. the AttachedRoutes field count MUST be set
for Listeners with condition Accepted: false and MUST count successfully
attached Routes that may themselves have Accepted: false conditions.
Uses for this field include troubleshooting Route attachment and
measuring blast radius/impact of changes to a Listener. | | | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#condition-v1-meta) array_ | Conditions describe the current condition of this listener. | | MaxItems: 8
| + + + + + + +#### ListenerSetSpec + + + +ListenerSetSpec defines the desired state of a ListenerSet. + + + +_Appears in:_ +- [XListenerSet](#xlistenerset) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `parentRef` _[ParentGatewayReference](#parentgatewayreference)_ | ParentRef references the Gateway that the listeners are attached to. | | | +| `listeners` _[ListenerEntry](#listenerentry) array_ | Listeners associated with this ListenerSet. Listeners define
logical endpoints that are bound on this referenced parent Gateway's addresses.
Listeners in a `Gateway` and their attached `ListenerSets` are concatenated
as a list when programming the underlying infrastructure. Each listener
name does not need to be unique across the Gateway and ListenerSets.
See ListenerEntry.Name for more details.
Implementations MUST treat the parent Gateway as having the merged
list of all listeners from itself and attached ListenerSets using
the following precedence:
1. "parent" Gateway
2. ListenerSet ordered by creation time (oldest first)
3. ListenerSet ordered alphabetically by “\{namespace\}/\{name\}”.
An implementation MAY reject listeners by setting the ListenerEntryStatus
`Accepted`` condition to False with the Reason `TooManyListeners`
If a listener has a conflict, this will be reported in the
Status.ListenerEntryStatus setting the `Conflicted` condition to True.
Implementations SHOULD be cautious about what information from the
parent or siblings are reported to avoid accidentally leaking
sensitive information that the child would not otherwise have access
to. This can include contents of secrets etc. | | MaxItems: 64
MinItems: 1
| + + +#### ListenerSetStatus + + + + + + + +_Appears in:_ +- [XListenerSet](#xlistenerset) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#condition-v1-meta) array_ | Conditions describe the current conditions of the ListenerSet.
Implementations MUST express ListenerSet conditions using the
`ListenerSetConditionType` and `ListenerSetConditionReason`
constants so that operators and tools can converge on a common
vocabulary to describe ListenerSet state.
Known condition types are:
* "Accepted"
* "Programmed" | [map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted] map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Programmed]] | MaxItems: 8
| +| `listeners` _[ListenerEntryStatus](#listenerentrystatus) array_ | Listeners provide status for each unique listener port defined in the Spec. | | MaxItems: 64
| + + + + + + + + +#### ParentGatewayReference + + + +ParentGatewayReference identifies an API object including its namespace, +defaulting to Gateway. + + + +_Appears in:_ +- [ListenerSetSpec](#listenersetspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `group` _[Group](#group)_ | Group is the group of the referent. | gateway.networking.k8s.io | | +| `kind` _[Kind](#kind)_ | Kind is kind of the referent. For example "Gateway". | Gateway | | +| `name` _[ObjectName](#objectname)_ | Name is the name of the referent. | | | +| `namespace` _[Namespace](#namespace)_ | Namespace is the namespace of the referent. If not present,
the namespace of the referent is assumed to be the same as
the namespace of the referring object. | | | + + + + + + + + +#### RequestRate + + + +RequestRate expresses a rate of requests over a given period of time. + + + +_Appears in:_ +- [RetryConstraint](#retryconstraint) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `count` _integer_ | Count specifies the number of requests per time interval.
Support: Extended | | Maximum: 1e+06
Minimum: 1
| +| `interval` _[Duration](#duration)_ | Interval specifies the divisor of the rate of requests, the amount of
time during which the given count of requests occur.
Support: Extended | | | + + +#### RetryConstraint + + + +RetryConstraint defines the configuration for when to retry a request. + + + +_Appears in:_ +- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `budget` _[BudgetDetails](#budgetdetails)_ | Budget holds the details of the retry budget configuration. | \{ interval:10s percent:20 \} | | +| `minRetryRate` _[RequestRate](#requestrate)_ | MinRetryRate defines the minimum rate of retries that will be allowable
over a specified duration of time.
The effective overall minimum rate of retries targeting the backend
service may be much higher, as there can be any number of clients which
are applying this setting locally.
This ensures that requests can still be retried during periods of low
traffic, where the budget for retries may be calculated as a very low
value.
Support: Extended | \{ count:10 interval:1s \} | | + + + + + + + + +#### XBackendTrafficPolicy + + + +XBackendTrafficPolicy defines the configuration for how traffic to a +target backend should be handled. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.x-k8s.io/v1alpha1` | | | +| `kind` _string_ | `XBackendTrafficPolicy` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[BackendTrafficPolicySpec](#backendtrafficpolicyspec)_ | Spec defines the desired state of BackendTrafficPolicy. | | | +| `status` _[PolicyStatus](#policystatus)_ | Status defines the current state of BackendTrafficPolicy. | | | + + +#### XListenerSet + + + +XListenerSet defines a set of additional listeners +to attach to an existing Gateway. + + + + + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `gateway.networking.x-k8s.io/v1alpha1` | | | +| `kind` _string_ | `XListenerSet` | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[ListenerSetSpec](#listenersetspec)_ | Spec defines the desired state of ListenerSet. | | | +| `status` _[ListenerSetStatus](#listenersetstatus)_ | Status defines the current state of ListenerSet. | \{ conditions:[map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Accepted] map[lastTransitionTime:1970-01-01T00:00:00Z message:Waiting for controller reason:Pending status:Unknown type:Programmed]] \} | | + + diff --git a/site-src/ko/stylesheets/extra.css b/site-src/ko/stylesheets/extra.css new file mode 100644 index 0000000000..83df9a8d60 --- /dev/null +++ b/site-src/ko/stylesheets/extra.css @@ -0,0 +1,43 @@ +/* Hide title in favor of logo */ +.md-header__topic { + display: none; +} + +/* Use Kubernetes color as primary */ +:root { + --md-primary-fg-color: #326ce5; +} + +/* Increase size of logo */ +.md-header__button.md-logo img, .md-header__button.md-logo svg { + height: 1.8rem; +} + +/* Always show tabs, even on smaller screens */ +@media screen and (max-width: 76.234375em) { + .md-header__button.md-logo { + display: block; + } + .md-tabs { + display: block; + } +} + +/* Rounded search box + results */ +.md-search__form { + border-radius: .5rem; +} + +[data-md-toggle=search]:checked~.md-header .md-search__form { + border-radius: .5rem .5rem 0 0; +} +[dir=ltr] .md-search__output { + border-radius: 0 0 .5rem .5rem; +} + +/* Center images */ +img.center { + display: block; + margin: 20px auto; + width: 550px; +} diff --git a/site-src/overrides/main.html b/site-src/overrides/main.html new file mode 100644 index 0000000000..d2c7ebbeb3 --- /dev/null +++ b/site-src/overrides/main.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} + +{% block site_meta %} + {{ super() }} + {# Add language metadata to HTML for language detection #} + {# This enables language-switch.js to detect the current language #} + {% if page and page.meta and page.meta.lang %} + + {% else %} + + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/site-src/stylesheets/extra.css b/site-src/stylesheets/extra.css index 83df9a8d60..42a87b9bc1 100644 --- a/site-src/stylesheets/extra.css +++ b/site-src/stylesheets/extra.css @@ -41,3 +41,94 @@ img.center { margin: 20px auto; width: 550px; } + +/* Language selector */ +.md-select.md-header__option { + position: relative; + margin-right: 0; +} + +.md-select .md-header__button { + background: transparent; + border: none; + color: rgba(255, 255, 255, 0.85); + padding: 0.5rem 1rem; + border-radius: 0; + cursor: pointer; + font-size: 0.75rem; + font-weight: 700; + text-transform: none; + display: flex; + align-items: center; + transition: color 0.125s; + text-decoration: none; + height: 100%; + min-height: 2.4rem; +} + +.md-select .md-header__button:hover { + color: white; +} + +.md-select .md-header__button:focus { + outline: none; +} + + + +.md-select__inner { + background-color: white; + border-radius: 0.2rem; + min-width: 140px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + z-index: 1000; + margin-top: 0.5rem; + border: 1px solid rgba(0, 0, 0, 0.1); +} + +.md-select__list { + padding: 0.25rem 0; +} + +.md-select__item { + margin: 0; +} + +.md-select__link { + color: rgba(0, 0, 0, 0.87); + padding: 0.5rem 1rem; + text-decoration: none; + display: block; + font-size: 0.75rem; + transition: background-color 0.125s; +} + +.md-select__link:hover { + background-color: rgba(0, 0, 0, 0.05); + color: rgba(0, 0, 0, 0.87); +} + +.md-select__link.current { + background-color: rgba(50, 108, 229, 0.1); + color: #326ce5; + font-weight: 500; +} + +/* Center align navigation tabs text */ +.md-tabs__link { + text-align: center; +} + +.md-tabs__item { + display: flex; + justify-content: center; +} + +/* Language specific display */ +body.is-korean .md-tabs__item:nth-child(-n+5) { + display: none !important; +} + +body.is-english .md-tabs__item:nth-child(n+6):nth-child(-n+10) { + display: none !important; +}