From 47fdff4a3ba0f263c8deed6dbc71c69aa3ce52e0 Mon Sep 17 00:00:00 2001 From: Jihoon Seo <46767780+jihoon-seo@users.noreply.github.com> Date: Mon, 8 Aug 2022 00:32:18 +0900 Subject: [PATCH] [ko] Reorg 'Windows in K8s' docs (#35423) * [ko] Split 'Windows resource mgmt' into new page * [ko] Split 'Windows security' into new page * [ko] Split 'Windows storage' into new page * [ko] Split 'Windows networking' into new page * [ko] Split 'Windows troubleshooting' into new page * [ko] Update 'Windows containers user guide' * [ko] Move 'Intro-Windows-in-K8s' * [ko] Update links for reorg-ed Windows pages * [ko] Reflect review suggestions * [ko] Reflect review suggestions (2) --- .../windows-resource-management.md | 79 + .../concepts/security/windows-security.md | 55 + .../services-networking/windows-networking.md | 164 ++ .../docs/concepts/storage/windows-storage.md | 71 + content/ko/docs/concepts/windows/_index.md | 2 +- content/ko/docs/concepts/windows/intro.md | 387 +++++ .../ko/docs/concepts/windows/user-guide.md | 75 +- .../flannel-master-kubectl-get-pods.png | Bin 111844 -> 0 bytes .../windows/intro-windows-in-kubernetes.md | 1358 ----------------- .../docs/tasks/debug/debug-cluster/windows.md | 175 +++ 10 files changed, 965 insertions(+), 1401 deletions(-) create mode 100644 content/ko/docs/concepts/configuration/windows-resource-management.md create mode 100644 content/ko/docs/concepts/security/windows-security.md create mode 100644 content/ko/docs/concepts/services-networking/windows-networking.md create mode 100644 content/ko/docs/concepts/storage/windows-storage.md create mode 100644 content/ko/docs/concepts/windows/intro.md delete mode 100644 content/ko/docs/setup/production-environment/windows/flannel-master-kubectl-get-pods.png delete mode 100644 content/ko/docs/setup/production-environment/windows/intro-windows-in-kubernetes.md create mode 100644 content/ko/docs/tasks/debug/debug-cluster/windows.md diff --git a/content/ko/docs/concepts/configuration/windows-resource-management.md b/content/ko/docs/concepts/configuration/windows-resource-management.md new file mode 100644 index 00000000000..db45d4ae220 --- /dev/null +++ b/content/ko/docs/concepts/configuration/windows-resource-management.md @@ -0,0 +1,79 @@ +--- +# reviewers: +# - jayunit100 +# - jsturtevant +# - marosset +# - perithompson +title: 윈도우 노드의 자원 관리 +content_type: concept +weight: 75 +--- + + + +이 페이지는 리눅스와 윈도우 간에 리소스를 관리하는 방법의 차이점을 간략하게 설명한다. + + + +리눅스 노드에서, {{< glossary_tooltip text="cgroup" term_id="cgroup" >}}이 +리소스 제어를 위한 파드 경계로서 사용된다. +컨테이너는 네트워크, 프로세스 및 파일시스템 격리를 위해 해당 경계 내에 생성된다. +cpu/io/memory 통계를 수집하기 위해 cgroup API를 사용할 수 있다. + +반대로, 윈도우는 시스템 네임스페이스 필터와 함께 +컨테이너별로 [잡(job) 오브젝트](https://docs.microsoft.com/windows/win32/procthread/job-objects)를 사용하여 +모든 프로세스를 컨테이너 안에 포함시키고 호스트와의 논리적 격리를 제공한다. +(잡 오브젝트는 윈도우의 프로세스 격리 메커니즘이며 +쿠버네티스의 {{< glossary_tooltip term_id="job" text="잡(Job)" >}}과는 다른 것이다.) + +네임스페이스 필터링 없이 윈도우 컨테이너를 실행할 수 있는 방법은 없다. +이는 곧 시스템 권한은 호스트 입장에서 주장할(assert) 수 없고, +이로 인해 특권을 가진(privileged) 컨테이너는 윈도우에서 사용할 수 없음을 의미한다. +또한 보안 계정 매니저(Security Account Manager, SAM)가 분리되어 있으므로 +컨테이너는 호스트의 ID를 가정(assume)할 수 없다. + +## 메모리 관리 {#resource-management-memory} + +윈도우에는 리눅스에는 있는 메모리 부족 프로세스 킬러가 없다. +윈도우는 모든 사용자 모드 메모리 할당을 항상 가상 메모리처럼 처리하며, 페이지파일(pagefile)이 필수이다. + +윈도우 노드는 프로세스를 위해 메모리를 오버커밋(overcommit)하지 않는다. +이로 인해 윈도우는 메모리 컨디션에 도달하는 방식이 리눅스와 다르며, +프로세스는 메모리 부족(OOM, out of memory) 종료를 겪는 대신 디스크에 페이징을 수행한다. +메모리가 오버프로비저닝(over-provision)되고 전체 물리 메모리가 고갈되면, +페이징으로 인해 성능이 저하될 수 있다. + +## CPU 관리 {#resource-management-cpu} + +윈도우는 각 프로세스에 할당되는 CPU 시간의 양을 제한할 수는 있지만, +CPU 시간의 최소량을 보장하지는 않는다. + +윈도우에서, kubelet은 kubelet 프로세스의 +[스케줄링 우선 순위](https://docs.microsoft.com/windows/win32/procthread/scheduling-priorities)를 설정하기 위한 명령줄 플래그인 +`--windows-priorityclass`를 지원한다. +이 플래그를 사용하면 윈도우 호스트에서 실행되는 kubelet 프로세스가 다른 프로세스보다 더 많은 CPU 시간 슬라이스를 할당받는다. +할당 가능한 값 및 각각의 의미에 대한 자세한 정보는 +[윈도우 프라이어리티 클래스](https://docs.microsoft.com/en-us/windows/win32/procthread/scheduling-priorities#priority-class)에서 확인할 수 있다. +실행 중인 파드가 kubelet의 CPU 사이클을 빼앗지 않도록 하려면, 이 플래그를 `ABOVE_NORMAL_PRIORITY_CLASS` 이상으로 설정한다. + +## 리소스 예약 {#resource-reservation} + +운영 체제, 컨테이너 런타임, 그리고 kubelet과 같은 쿠버네티스 호스트 프로세스가 사용하는 메모리 및 CPU를 고려하기 위해, +kubelet 플래그 `--kube-reserved` 및 `--system-reserved`를 사용하여 +메모리 및 CPU 리소스의 예약이 가능하다 (그리고 필요하다). +윈도우에서 이들 값은 노드의 +[할당 가능(allocatable)](/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable) 리소스의 계산에만 사용된다. + +{{< caution >}} +워크로드를 배포할 때, 컨테이너에 메모리 및 CPU 리소스 제한을 걸자. +이 또한 NodeAllocatable에서 차감되며, 클러스터 수준 스케줄러가 각 파드를 어떤 노드에 할당할지 결정하는 데 도움을 준다. + +제한을 설정하지 않은 파드를 스케줄링하면 윈도우 노드가 오버프로비전될 수 있으며, +극단적인 경우 노드가 비정상 상태(unhealthy)로 될 수도 있다. +{{< /caution >}} + +윈도우에서는, 메모리를 최소 2GB 이상 예약하는 것이 좋다. + +얼마나 많은 양의 CPU를 예약할지 결정하기 위해, +각 노드의 최대 파드 수를 확인하고 해당 노드의 시스템 서비스의 CPU 사용량을 모니터링한 뒤, +워크로드 요구사항을 충족하는 값을 선택한다. diff --git a/content/ko/docs/concepts/security/windows-security.md b/content/ko/docs/concepts/security/windows-security.md new file mode 100644 index 00000000000..ba984aade03 --- /dev/null +++ b/content/ko/docs/concepts/security/windows-security.md @@ -0,0 +1,55 @@ +--- +# reviewers: +# - jayunit100 +# - jsturtevant +# - marosset +# - perithompson +title: 윈도우 노드에서의 보안 +content_type: concept +weight: 40 +--- + + + +이 페이지에서는 윈도우 운영 체제에서의 보안 고려 사항 및 추천 사례에 대해 기술한다. + + + +## 노드의 시크릿 데이터 보호 + +윈도우에서, 시크릿에 있던 데이터는 노드의 로컬 스토리지에 +평문으로 기록된다(리눅스는 tmpfs 또는 인메모리 파일시스템에 기록). +클러스터 운영자로서, 다음 2 가지의 추가 사항을 고려해야 한다. + +1. 파일 ACL을 사용하여 시크릿의 파일 위치를 보호한다. +1. [BitLocker](https://docs.microsoft.com/windows/security/information-protection/bitlocker/bitlocker-how-to-deploy-on-windows-server)를 사용하여 볼륨 수준의 암호화를 적용한다. + +## 컨테이너 사용자 + +윈도우 파드 또는 컨테이너에 +[RunAsUsername](/ko/docs/tasks/configure-pod-container/configure-runasusername/)을 설정하여 +해당 컨테이너 프로세스를 실행할 사용자를 지정할 수 있다. +이는 [RunAsUser](/ko/docs/concepts/security/pod-security-policy/#사용자-및-그룹)와 대략적으로 동등하다. + +윈도우 컨테이너는 ContainerUser와 ContainerAdministrator의 2 개의 기본 사용자 계정을 제공한다. +이 두 사용자 계정이 어떻게 다른지는 마이크로소프트의 _안전한 윈도우 컨테이너_ 문서 내의 +[언제 ContainerAdmin 및 ContainerUser 사용자 계정을 사용해야 하는가](https://docs.microsoft.com/virtualization/windowscontainers/manage-containers/container-security#when-to-use-containeradmin-and-containeruser-user-accounts)를 참고한다. + +컨테이너 빌드 과정에서 컨테이너 이미지에 로컬 사용자를 추가할 수 있다. + +{{< note >}} + +* [Nano Server](https://hub.docker.com/_/microsoft-windows-nanoserver) 기반 이미지는 기본적으로 `ContainerUser`로 실행된다 +* [Server Core](https://hub.docker.com/_/microsoft-windows-servercore) 기반 이미지는 기본적으로 `ContainerAdministrator`로 실행된다 + +{{< /note >}} + +[그룹 관리 서비스 어카운트](/ko/docs/tasks/configure-pod-container/configure-gmsa/)를 활용하여 윈도우 컨테이너를 Active Directory 사용자로 실행할 수도 있다. + +## 파드-수준 보안 격리 + +리눅스 특유의 파드 보안 컨텍스트 메커니즘(예: SELinux, AppArmor, Seccomp, +또는 커스텀 POSIX 기능)은 윈도우 노드에서 지원되지 않는다. + +특권을 가진(Privileged) 컨테이너는 윈도우에서 [지원되지 않는다](/ko/docs/concepts/windows/intro/#compatibility-v1-pod-spec-containers-securitycontext). +대신, 리눅스에서 권한 있는 컨테이너가 할 수 있는 작업 중 많은 부분을 윈도우에서 수행하기 위해 [HostProcess 컨테이너](/docs/tasks/configure-pod-container/create-hostprocess-pod)를 사용할 수 있다. diff --git a/content/ko/docs/concepts/services-networking/windows-networking.md b/content/ko/docs/concepts/services-networking/windows-networking.md new file mode 100644 index 00000000000..400e9c51c13 --- /dev/null +++ b/content/ko/docs/concepts/services-networking/windows-networking.md @@ -0,0 +1,164 @@ +--- +# reviewers: +# - aravindhp +# - jayunit100 +# - jsturtevant +# - marosset +title: 윈도우에서의 네트워킹 +content_type: concept +weight: 75 +--- + + + +쿠버네티스는 리눅스 및 윈도우 노드를 지원한다. +단일 클러스터 내에 두 종류의 노드를 혼합할 수 있다. +이 페이지에서는 윈도우 운영 체제에서의 네트워킹에 대한 개요를 제공한다. + + +## 윈도우에서의 컨테이너 네트워킹 {#networking} + +윈도우 컨테이너에 대한 네트워킹은 +[CNI 플러그인](/ko/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)을 통해 노출된다. +윈도우 컨테이너는 네트워킹과 관련하여 가상 머신과 유사하게 작동한다. +각 컨테이너에는 Hyper-V 가상 스위치(vSwitch)에 연결된 가상 네트워크 어댑터(vNIC)가 있다. +호스트 네트워킹 서비스(HNS)와 호스트 컴퓨팅 서비스(HCS)는 함께 작동하여 +컨테이너를 만들고 컨테이너 vNIC을 네트워크에 연결한다. +HCS는 컨테이너 관리를 담당하는 반면 +HNS는 다음과 같은 네트워킹 리소스 관리를 담당한다. + +* 가상 네트워크(vSwitch 생성 포함) +* 엔드포인트 / vNIC +* 네임스페이스 +* 정책(패킷 캡슐화, 로드 밸런싱 규칙, ACL, NAT 규칙 등) + +윈도우 HNS(호스트 네트워킹 서비스)와 가상 스위치는 +네임스페이스를 구현하고 파드 또는 컨테이너에 필요한 가상 NIC을 만들 수 있다. +그러나 DNS, 라우트, 메트릭과 같은 많은 구성은 +리눅스에서와 같이 `/etc/` 내의 파일이 아닌 윈도우 레지스트리 데이터베이스에 저장된다. +컨테이너의 윈도우 레지스트리는 호스트 레지스트리와 별개이므로 +호스트에서 컨테이너로 `/etc/resolv.conf`를 매핑하는 것과 같은 개념은 리눅스에서와 동일한 효과를 갖지 않는다. +해당 컨테이너의 컨텍스트에서 실행되는 윈도우 API를 사용하여 구성해야 한다. +따라서 CNI 구현에서는 파일 매핑에 의존하는 대신 +HNS를 호출하여 네트워크 세부 정보를 파드 또는 컨테이너로 전달해야 한다. + +## 네트워크 모드 + +윈도우는 L2bridge, L2tunnel, Overlay, Transparent 및 NAT의 다섯 가지 네트워킹 드라이버/모드를 지원한다. +윈도우와 리눅스 워커 노드가 있는 이기종 클러스터에서는 +윈도우와 리눅스 모두에서 호환되는 네트워킹 솔루션을 선택해야 한다. +윈도우에서 다음과 같은 out-of-tree 플러그인이 지원되며, +어떠한 경우에 각 CNI를 사용하면 좋은지도 소개한다. + +| 네트워크 드라이버 | 설명 | 컨테이너 패킷 수정 | 네트워크 플러그인 | 네트워크 플러그인 특성 | +| -------------- | ----------- | ------------------------------ | --------------- | ------------------------------ | +| L2bridge | 컨테이너는 외부 vSwitch에 연결된다. 컨테이너는 언더레이 네트워크에 연결된다. 하지만 인그레스/이그레스시에 재작성되기 때문에 물리적 네트워크가 컨테이너 MAC을 학습할 필요가 없다. | MAC은 호스트 MAC에 다시 쓰여지고, IP는 HNS OutboundNAT 정책을 사용하여 호스트 IP에 다시 쓰여질 수 있다. | [win-bridge](https://github.com/containernetworking/plugins/tree/master/plugins/main/windows/win-bridge), [Azure-CNI](https://github.com/Azure/azure-container-networking/blob/master/docs/cni.md), Flannel 호스트-게이트웨이는 win-bridge를 사용한다. | win-bridge는 L2bridge 네트워크 모드를 사용하고, 컨테이너를 호스트의 언더레이에 연결하여 최상의 성능을 제공한다. 노드 간 연결을 위해 사용자 정의 경로(user-defined routes, UDR)가 필요하다. | +| L2Tunnel | 이것은 Azure에서만 사용되는 l2bridge의 특별 케이스다. 모든 패킷은 SDN 정책이 적용되는 가상화 호스트로 전송된다. | MAC 재작성되고, 언더레이 네트워크 상에서 IP가 보인다. | [Azure-CNI](https://github.com/Azure/azure-container-networking/blob/master/docs/cni.md) | Azure-CNI를 사용하면 컨테이너를 Azure vNET과 통합할 수 있으며, [Azure Virtual Network](https://azure.microsoft.com/en-us/services/virtual-network/)에서 제공하는 기능 집합을 활용할 수 있다. 예를 들어, Azure 서비스에 안전하게 연결하거나 Azure NSG를 사용한다. [azure-cni](https://docs.microsoft.com/azure/aks/concepts-network#azure-cni-advanced-networking) 예제를 참고한다. | +| Overlay | 컨테이너에는 외부 vSwitch에 연결된 vNIC이 제공된다. 각 오버레이 네트워크는 사용자 지정 IP 접두사로 정의된 자체 IP 서브넷을 가져온다. 오버레이 네트워크 드라이버는 VXLAN 캡슐화를 사용한다. | 외부 헤더로 캡슐화된다. | [win-overlay](https://github.com/containernetworking/plugins/tree/master/plugins/main/windows/win-overlay), Flannel VXLAN (win-overlay 사용) | win-overlay는 가상 컨테이너 네트워크를 호스트의 언더레이에서 격리하려는 경우(예: 보안 상의 이유로) 사용해야 한다. 데이터 센터의 IP에 제한이 있는 경우, (다른 VNID 태그가 있는) 다른 오버레이 네트워크에 IP를 재사용할 수 있다. 이 옵션을 사용하려면 Windows Server 2019에서 [KB4489899](https://support.microsoft.com/help/4489899)가 필요하다. | +| Transparent ([ovn-kubernetes](https://github.com/openvswitch/ovn-kubernetes)의 특수한 유스케이스) | 외부 vSwitch가 필요하다. 컨테이너는 논리적 네트워크(논리적 스위치 및 라우터)를 통해 파드 내 통신을 가능하게 하는 외부 vSwitch에 연결된다. | 패킷은 [GENEVE](https://datatracker.ietf.org/doc/draft-gross-geneve/) 또는 [STT](https://datatracker.ietf.org/doc/draft-davie-stt/) 터널링을 통해 캡슐화되는데, 동일한 호스트에 있지 않은 파드에 도달하기 위한 터널링을 한다.
패킷은 ovn 네트워크 컨트롤러에서 제공하는 터널 메타데이터 정보를 통해 전달되거나 삭제된다.
NAT는 north-south 통신(데이터 센터와 클라이언트, 네트워크 상의 데이터 센터 외부와의 통신)을 위해 수행된다. | [ovn-kubernetes](https://github.com/openvswitch/ovn-kubernetes) | [Ansible을 통해 배포](https://github.com/openvswitch/ovn-kubernetes/tree/master/contrib)한다. 분산 ACL은 쿠버네티스 정책을 통해 적용할 수 있다. IPAM을 지원한다. kube-proxy 없이 로드 밸런싱을 수행할 수 있다. NAT를 수행할 때 iptables/netsh를 사용하지 않고 수행된다. | +| NAT (*쿠버네티스에서 사용되지 않음*) | 컨테이너에는 내부 vSwitch에 연결된 vNIC이 제공된다. DNS/DHCP는 [WinNAT](https://techcommunity.microsoft.com/t5/virtualization/windows-nat-winnat-capabilities-and-limitations/ba-p/382303)라는 내부 컴포넌트를 사용하여 제공된다. | MAC 및 IP는 호스트 MAC/IP에 다시 작성된다. | [nat](https://github.com/Microsoft/windows-container-networking/tree/master/plugins/nat) | 완전성을 위해 여기에 포함되었다. | + +위에서 설명한 대로, [플란넬(Flannel)](https://github.com/coreos/flannel) +[CNI 플러그인](https://github.com/flannel-io/cni-plugin)은 +[VXLAN 네트워크 백엔드](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#vxlan)(**베타 지원**, win-overlay에 위임) 및 +[host-gateway network backend](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#host-gw)(안정적인 지원, win-bridge에 위임)를 통해 +윈도우에서도 [지원](https://github.com/flannel-io/cni-plugin#windows-support-experimental)한다. + +이 플러그인은 자동 노드 서브넷 임대 할당과 HNS 네트워크 생성을 위해 +윈도우의 Flannel 데몬(Flanneld)과 함께 작동할 수 있도록 +참조 CNI 플러그인(win-overlay, win-bridge) 중 하나에 대한 위임을 지원한다. +이 플러그인은 자체 구성 파일 (cni.conf)을 읽고, +이를 FlannelD가 생성한 `subnet.env` 파일의 환경 변수와 결합한다. +이후 이를 네트워크 연결을 위한 참조 CNI 플러그인 중 하나에 위임하고, +노드-할당 서브넷을 포함하는 올바른 구성을 IPAM 플러그인(예: `host-local`)으로 보낸다. + +노드, 파드 및 서비스 오브젝트의 경우, +TCP/UDP 트래픽에 대해 다음 네트워크 흐름이 지원된다. + +* 파드 → 파드(IP) +* 파드 → 파드(이름) +* 파드 → 서비스(Cluster IP) +* 파드 → 서비스(PQDN, 단 "."이 없는 경우에만) +* 파드 → 서비스(FQDN) +* 파드 → External(IP) +* 파드 → External(DNS) +* 노드 → 파드 +* 파드 → 노드 + +## IP 주소 관리 (IPAM) {#ipam} + +The following IPAM options are supported on Windows: + +* [host-local](https://github.com/containernetworking/plugins/tree/master/plugins/ipam/host-local) +* [azure-vnet-ipam](https://github.com/Azure/azure-container-networking/blob/master/docs/ipam.md)(azure-cni 전용) +* [Windows Server IPAM](https://docs.microsoft.com/windows-server/networking/technologies/ipam/ipam-top) (IPAM이 설정되지 않은 경우에 대한 폴백(fallback) 옵션) + +## Load balancing and Services + +쿠버네티스 {{< glossary_tooltip text="서비스" term_id="service" >}}는 +논리적 파드 집합 및 네트워크에서 해당 파드로 접근할 수 있는 수단을 정의하는 추상화이다. +윈도우 노드가 포함된 클러스터에서, 다음과 같은 종류의 서비스를 사용할 수 있다. + +* `NodePort` +* `ClusterIP` +* `LoadBalancer` +* `ExternalName` + +윈도우 컨테이너 네트워킹은 리눅스 네트워킹과 몇 가지 중요한 차이점을 갖는다. +[윈도우 컨테이너 네트워킹에 대한 마이크로소프트 문서](https://docs.microsoft.com/en-us/virtualization/windowscontainers/container-networking/architecture)에서 +상세 사항과 배경 지식을 제공한다. + +윈도우에서는 다음 설정을 사용하여 +서비스 및 로드 밸런싱 동작을 구성할 수 있다. + +{{< table caption="윈도우 서비스 구성" >}} +| 기능 | 설명 | 지원하는 최소 윈도우 OS 빌드 | 활성화하는 방법 | +| ------- | ----------- | -------------------------- | ------------- | +| 세션 어피니티 | 특정 클라이언트의 연결이 매번 동일한 파드로 전달되도록 한다. | Windows Server 2022 | `service.spec.sessionAffinity`를 "ClientIP"로 설정 | +| 서버 직접 반환 (DSR, Direct Server Return) | IP 주소 수정 및 LBNAT가 컨테이너 vSwitch 포트에서 직접 발생하는 로드 밸런싱 모드. 서비스 트래픽은 소스 IP가 원래 파드 IP로 설정된 상태로 도착한다. | Windows Server 2019 | kube-proxy에 `--feature-gates="WinDSR=true" --enable-dsr=true` 플래그를 설정한다. | +| 목적지 보존(Preserve-Destination) | 서비스 트래픽의 DNAT를 스킵하여, 백엔드 파드에 도달하는 패킷에서 목적지 서비스의 가상 IP를 보존한다. 또한 노드-노드 전달을 비활성화한다. | Windows Server, version 1903 | 서비스 어노테이션에 `"preserve-destination": "true"`를 설정하고 kube-proxy에 DSR을 활성화한다. | +| IPv4/IPv6 이중 스택 네트워킹 | 클러스터 내/외부에 네이티브 IPv4-to-IPv4 통신 및 IPv6-to-IPv6 통신 활성화 | Windows Server 2019 | [IPv4/IPv6 이중 스택](#ipv4ipv6-dual-stack)을 참고한다. | +| 클라이언트 IP 보존 | 인그레스 트래픽의 소스 IP가 유지되도록 한다. 또한 노드-노드 전달을 비활성화한다. | Windows Server 2019 | Set `service.spec.externalTrafficPolicy`를 "Local"로 설정하고 kube-proxy에 DSR을 활성화한다. | +{{< /table >}} + +{{< warning >}} +목적지 노드가 Windows Server 2022를 실행 중인 경우, 오버레이 네트워킹에서 NodePort 서비스에 문제가 있음이 알려져 있다. +이 이슈를 완전히 피하려면, 서비스에 `externalTrafficPolicy: Local`를 설정한다. + +KB5005619 또는 그 이상이 설치된 Windows Server 2022의 경우, l2bridge 네트워크에서 파드 간 연결성에 문제가 있음이 알려져 있다. +이 이슈를 우회하고 파드 간 연결성을 복구하기 위해, kube-proxy의 WinDSR 기능을 비활성화할 수 있다. + +이 이슈들을 해결하기 위해서는 운영 체제를 패치해야 한다. +이와 관련해서는 https://github.com/microsoft/Windows-Containers/issues/204 를 참고한다. +{{< /warning >}} + +## 제한 + +다음 네트워킹 기능은 윈도우 노드에서 지원되지 _않는다_. + +* 호스트 네트워킹 모드 +* 노드 자체에서 로컬 NodePort로의 접근(다른 노드 또는 외부 클라이언트에서는 가능) +* 단일 서비스에 대해 64개를 초과하는 백엔드 파드 (또는 고유한 목적지 주소) +* 오버레이 네트워크에 연결된 윈도우 파드 간의 IPv6 통신 +* non-DSR 모드에서의 로컬 트래픽 정책(Local Traffic Policy) +* win-overlay, win-bridge, Azure-CNI 플러그인을 통해 ICMP 프로토콜을 사용하는 아웃바운드 통신. + 특히, 윈도우 데이터 플레인([VFP](https://www.microsoft.com/en-us/research/project/azure-virtual-filtering-platform/))은 + ICMP 패킷 치환을 지원하지 않는다. 이것은 다음을 의미한다. + * 동일한 네트워크 내의 목적지로 전달되는 ICMP 패킷(예: ping을 통한 파드 간 통신)은 + 예상대로 제한 없이 작동한다. + * TCP/UDP 패킷은 예상대로 제한 없이 작동한다. + * 원격 네트워크를 통과하도록 지정된 ICMP 패킷(예: ping을 통한 파드에서 외부 인터넷으로의 통신)은 + 치환될 수 없으므로 소스로 다시 라우팅되지 않는다. + * TCP/UDP 패킷은 여전히 치환될 수 있기 때문에 `ping `을 + `curl `으로 대체하여 외부와의 연결을 디버깅할 수 있다. + +다른 제한도 존재한다. + +* 윈도우 참조 네트워크 플러그인 win-bridge와 win-overlay는 + 현재 `CHECK` 구현 누락으로 인해 + [CNI 사양](https://github.com/containernetworking/cni/blob/master/SPEC.md) v0.4.0을 구현하지 않는다. +* Flannel VXLAN CNI는 윈도우에서 다음과 같은 제한이 있다. + * 노드-파드 연결은 Flannel v0.12.0(또는 그 이상) 상의 로컬 파드에서만 가능하다. + * Flannel은 VNI 4096 및 UDP 4789 포트만 사용하도록 제한된다. + 이 파라미터에 대한 더 자세한 사항은 + 공식 [Flannel VXLAN](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#vxlan) 백엔드 문서를 참조한다. diff --git a/content/ko/docs/concepts/storage/windows-storage.md b/content/ko/docs/concepts/storage/windows-storage.md new file mode 100644 index 00000000000..e84fe66347b --- /dev/null +++ b/content/ko/docs/concepts/storage/windows-storage.md @@ -0,0 +1,71 @@ +--- +# reviewers: +# - jingxu97 +# - mauriciopoppe +# - jayunit100 +# - jsturtevant +# - marosset +# - aravindhp +title: 윈도우 스토리지 +content_type: concept +--- + + + +이 페이지는 윈도우 운영 체제에서의 스토리지 개요를 제공한다. + + + +## 퍼시스턴트 스토리지 {#storage} + +윈도우는 계층 구조의 파일시스템 드라이버를 사용하여 +컨테이너 레이어를 마운트하고 NTFS 기반 파일시스템의 복제본을 생성한다. +컨테이너 내의 모든 파일 경로는 해당 컨테이너 컨텍스트 내에서만 인식 가능하다. + +* 도커를 사용할 때, 볼륨 마운트는 컨테이너 내의 디렉토리로만 지정할 수 있으며, 개별 파일로는 지정할 수 없다. + 이 제약 사항은 containerd에는 적용되지 않는다. +* 볼륨 마운트는 파일 또는 디렉토리를 호스트 파일시스템으로 투영(project)할 수 없다. +* 윈도우 레지스트리와 SAM 데이터케이스에 쓰기 권한이 항상 필요하기 때문에, + 읽기 전용 파일시스템은 지원되지 않는다. 다만, 읽기 전용 볼륨은 지원된다. +* 볼륨 사용자-마스크 및 퍼미션은 사용할 수 있다. + 호스트와 컨테이너 간에 SAM이 공유되지 않기 때문에, 둘 간의 매핑이 존재하지 않는다. + 모든 퍼미션은 해당 컨테이너 컨텍스트 내에서만 처리된다. + +결과적으로, 윈도우 노드에서는 다음 스토리지 기능이 지원되지 않는다. + +* 볼륨 서브패스(subpath) 마운트: 윈도우 컨테이너에는 전체 볼륨만 마운트할 수 있다. +* 시크릿을 위한 서브패스 볼륨 마운팅 +* 호스트 마운트 투영(projection) +* 읽기 전용 루트 파일시스템 (매핑된 볼륨은 여전히 `readOnly`를 지원한다) +* 블록 디바이스 매핑 +* 메모리를 스토리지 미디어로 사용하기 (예를 들어, `emptyDir.medium`를 `Memory`로 설정하는 경우) +* uid/gid, 사용자 별 리눅스 파일시스템 권한과 같은 파일시스템 기능 +* [DefaultMode을 이용하여 시크릿 퍼미션](/ko/docs/concepts/configuration/secret/#시크릿-파일-퍼미션) 설정하기 (UID/GID 의존성 때문에) +* NFS 기반 스토리지/볼륨 지원 +* 마운트된 볼륨 확장하기 (resizefs) + +쿠버네티스 {{< glossary_tooltip text="볼륨" term_id="volume" >}}을 사용하여 +데이터 지속성(persistence) 및 파드 볼륨 공유 요구 사항이 있는 +복잡한 애플리케이션을 쿠버네티스에 배포할 수 있다. +특정 스토리지 백엔드 또는 프로토콜과 연관된 퍼시스턴트 볼륨의 관리는 +볼륨 프로비저닝/디프로비저닝/리사이징, +쿠버네티스 노드로의 볼륨 연결(attaching) 및 해제(detaching), +데이터를 보존해야 하는 파드 내 개별 컨테이너로의 볼륨 마운트 및 해제 같은 동작을 포함한다. + +볼륨 관리 구성 요소는 쿠버네티스 볼륨 +[플러그인](/ko/docs/concepts/storage/volumes/#volume-types) 형태로 제공된다. +윈도우는 다음의 광역 쿠버네티스 볼륨 플러그인 클래스를 지원한다. + +* [`FlexVolume 플러그인`](/ko/docs/concepts/storage/volumes/#flexVolume) + * FlexVolumes은 1.23부터 사용 중단되었음에 유의한다. +* [`CSI 플러그인`](/ko/docs/concepts/storage/volumes/#csi) + +##### 인-트리(In-tree) 볼륨 플러그인 + +다음의 인-트리 플러그인은 윈도우 노드에서의 퍼시스턴트 스토리지를 지원한다. + +* [`awsElasticBlockStore`](/ko/docs/concepts/storage/volumes/#awselasticblockstore) +* [`azureDisk`](/ko/docs/concepts/storage/volumes/#azuredisk) +* [`azureFile`](/ko/docs/concepts/storage/volumes/#azurefile) +* [`gcePersistentDisk`](/ko/docs/concepts/storage/volumes/#gcepersistentdisk) +* [`vsphereVolume`](/ko/docs/concepts/storage/volumes/#vspherevolume) diff --git a/content/ko/docs/concepts/windows/_index.md b/content/ko/docs/concepts/windows/_index.md index 06562362393..e7113a09537 100644 --- a/content/ko/docs/concepts/windows/_index.md +++ b/content/ko/docs/concepts/windows/_index.md @@ -1,4 +1,4 @@ --- -title: "쿠버네티스에서 윈도우" +title: "쿠버네티스에서의 윈도우" weight: 50 --- diff --git a/content/ko/docs/concepts/windows/intro.md b/content/ko/docs/concepts/windows/intro.md new file mode 100644 index 00000000000..c66767c1dde --- /dev/null +++ b/content/ko/docs/concepts/windows/intro.md @@ -0,0 +1,387 @@ +--- +# reviewers: +# - jayunit100 +# - jsturtevant +# - marosset +# - perithompson +title: 쿠버네티스에서의 윈도우 컨테이너 +content_type: concept +weight: 65 +--- + + + +윈도우 애플리케이션은 많은 조직에서 실행되는 서비스 및 애플리케이션의 상당 부분을 구성한다. +[윈도우 컨테이너](https://aka.ms/windowscontainers)는 +프로세스와 패키지 종속성을 캡슐화하는 현대적인 방법을 제공하여, +데브옵스(DevOps) 사례를 더욱 쉽게 사용하고 윈도우 애플리케이션의 클라우드 네이티브 패턴을 따르도록 한다. + +윈도우 기반 애플리케이션과 리눅스 기반 애플리케이션에 투자한 조직은 +워크로드를 관리하기 위해 별도의 오케스트레이터를 찾을 필요가 없으므로, +운영 체제와 관계없이 +배포 전반에 걸쳐 운영 효율성이 향상된다. + + + +## 쿠버네티스에서의 윈도우 노드 + +쿠버네티스에서 윈도우 컨테이너 오케스트레이션을 활성화하려면, +기존 리눅스 클러스터에 윈도우 노드를 추가한다. +쿠버네티스에서 {{< glossary_tooltip text="파드" term_id="pod" >}} 내의 윈도우 컨테이너를 스케줄링하는 것은 +리눅스 기반 컨테이너를 스케줄링하는 것과 유사하다. + +윈도우 컨테이너를 실행하려면, +쿠버네티스 클러스터가 여러 운영 체제를 포함하고 있어야 한다. +{{< glossary_tooltip text="컨트롤 플레인" term_id="control-plane" >}}은 리눅스에서만 실행할 수 있는 반면, +워커 노드는 윈도우 또는 리눅스를 실행할 수 있다. + +{{< glossary_tooltip text="노드" term_id="node" >}}의 운영 체제가 +Windows Server 2019인 경우에만 +윈도우 노드로써 [사용할 수 있다](#windows-os-version-support). + +이 문서에서 *윈도우 컨테이너*라는 용어는 프로세스 격리 기반의 윈도우 컨테이너를 의미한다. +쿠버네티스는 [Hyper-V 격리](https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/hyperv-container) 기반의 +윈도우 컨테이너를 지원하지 않는다. + +## 호환성 및 제한 {#limitations} + +일부 노드 기능은 특정 [컨테이너 런타임](#container-runtime)을 사용할 때에만 이용 가능하며, +윈도우 노드에서 사용할 수 없는 기능도 있다. +예시는 다음과 같다. + +* HugePages: 윈도우 컨테이너에서 지원되지 않음 +* 특권을 가진(Privileged) 컨테이너: 윈도우 컨테이너에서 지원되지 않음. + [HostProcess 컨테이너](/docs/tasks/configure-pod-container/create-hostprocess-pod/)가 비슷한 기능을 제공한다. +* TerminationGracePeriod: containerD를 필요로 한다. + +공유 네임스페이스(shared namespaces)의 모든 기능이 지원되는 것은 아니다. +자세한 내용은 [API 호환성](#api)을 참조한다. + +[윈도우 OS 버전 호환성](#windows-os-version-support)에서 +쿠버네티스와의 동작이 테스트된 윈도우 버전 상세사항을 확인한다. + +API 및 kubectl의 관점에서, 윈도우 컨테이너는 리눅스 기반 컨테이너와 거의 같은 방식으로 작동한다. +그러나, 주요 기능에서 몇 가지 주목할 만한 차이점이 있으며, +이 섹션에서 소개된다. + +### 리눅스와의 비교 {#compatibility-linux-similarities} + +윈도우에서 주요 쿠버네티스 요소는 리눅스와 동일한 방식으로 작동한다. +이 섹션에서는 몇 가지 주요 워크로드 추상화 및 이들이 윈도우에서 어떻게 매핑되는지를 다룬다. + +* [파드](/ko/docs/concepts/workloads/pods/) + + 파드는 쿠버네티스의 기본 빌딩 블록이며, + 이는 쿠버네티스 오브젝트 모델에서 생성하고 배포하는 가장 작고 간단한 단위임을 의미한다. + 동일한 파드에 윈도우 컨테이너와 리눅스 컨테이너를 배포할 수 없다. + 파드의 모든 컨테이너는 단일 노드로 스케줄되며 이 때 각 노드는 특정 플랫폼 및 아키텍처를 갖는다. + 다음과 같은 파드 기능, 속성 및 이벤트가 윈도우 컨테이너에서 지원된다. + + * 프로세스 격리 및 볼륨 공유 기능을 갖춘 파드 당 하나 또는 여러 개의 컨테이너 + * 파드의 `status` 필드 + * 준비성 프로브(readinessprobe), 활성 프로브(liveness probe) 및 시작 프로브(startup probe) + * postStart 및 preStop 컨테이너 라이프사이클 훅 + * 컨피그맵(ConfigMap), 시크릿(Secrets): 환경 변수 또는 볼륨 형태로 + * `emptyDir` 볼륨 + * 명명된 파이프 호스트 마운트 + * 리소스 제한 + * OS 필드: + + 특정 파드가 윈도우 컨테이너를 사용하고 있다는 것을 나타내려면 `.spec.os.name` 필드를 `windows`로 설정해야 한다. + 이 필드가 인식되도록 하기 위해서는 `IdentifyPodOS` 기능 게이트가 활성화되어야 한다. + + {{< note >}} + 쿠버네티스 1.24부터, `IdentifyPodOS` 기능 게이트는 베타 단계이며 기본적으로 활성화되어 있다. + {{< /note >}} + + `IdentifyPodOS` 기능 게이트가 활성화되어 있고 `.spec.os.name` 필드를 `windows`로 설정했다면, + 해당 파드의 `.spec` 내의 다음 필드는 설정하지 않아야 한다. + + * `spec.hostPID` + * `spec.hostIPC` + * `spec.securityContext.seLinuxOptions` + * `spec.securityContext.seccompProfile` + * `spec.securityContext.fsGroup` + * `spec.securityContext.fsGroupChangePolicy` + * `spec.securityContext.sysctls` + * `spec.shareProcessNamespace` + * `spec.securityContext.runAsUser` + * `spec.securityContext.runAsGroup` + * `spec.securityContext.supplementalGroups` + * `spec.containers[*].securityContext.seLinuxOptions` + * `spec.containers[*].securityContext.seccompProfile` + * `spec.containers[*].securityContext.capabilities` + * `spec.containers[*].securityContext.readOnlyRootFilesystem` + * `spec.containers[*].securityContext.privileged` + * `spec.containers[*].securityContext.allowPrivilegeEscalation` + * `spec.containers[*].securityContext.procMount` + * `spec.containers[*].securityContext.runAsUser` + * `spec.containers[*].securityContext.runAsGroup` + + 위의 리스트에서 와일드카드(`*`)는 목록의 모든 요소를 가리킨다. + 예를 들어, `spec.containers[*].securityContext`는 + 모든 컨테이너의 시큐리티컨텍스트(SecurityContext) 오브젝트를 나타낸다. + 위의 필드 중 하나라도 설정되어 있으면, API 서버는 해당 파드는 수용하지 않을 것이다. + +* 다음과 같은 [워크로드 리소스](/ko/docs/concepts/workloads/controllers/): + * 레플리카셋(ReplicaSet) + * 디플로이먼트(Deployment) + * 스테이트풀셋(StatefulSet) + * 데몬셋(DaemonSet) + * 잡(Job) + * 크론잡(CronJob) + * 레플리케이션컨트롤러(ReplicationController) +* {{< glossary_tooltip text="서비스" term_id="service" >}} + [로드 밸런싱과 서비스](#load-balancing-and-services)에서 상세 사항을 확인한다. + +파드, 워크로드 리소스 및 서비스는 +쿠버네티스에서 윈도우 워크로드를 관리하는 데 중요한 요소이다. +그러나 그 자체만으로는 동적인 클라우드 네이티브 환경에서 +윈도우 워크로드의 적절한 라이프사이클 관리를 수행하기에 충분하지 않다. + +* `kubectl exec` +* 파드 및 컨테이너 메트릭 +* {{< glossary_tooltip text="Horizontal pod autoscaling" term_id="horizontal-pod-autoscaler" >}} +* {{< glossary_tooltip text="리소스 쿼터(Resource quota)" term_id="resource-quota" >}} +* 스케쥴러 선점(preemption) + +### kubelet을 위한 명령줄 옵션 {#kubelet-compatibility} + +윈도우에서는 일부 kubelet 명령줄 옵션이 다르게 동작하며, 아래에 설명되어 있다. + +* `--windows-priorityclass`를 사용하여 kubelet 프로세스의 스케줄링 우선 순위를 설정할 수 있다. + ([CPU 리소스 관리](/ko/docs/concepts/configuration/windows-resource-management/#resource-management-cpu) 참고) +* `--kube-reserved`, `--system-reserved` 및 `--eviction-hard` 플래그는 + [NodeAllocatable](/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable)을 업데이트한다. +* `--enforce-node-allocable`을 이용한 축출은 구현되어 있지 않다. +* `--eviction-hard` 및 `--eviction-soft`를 이용한 축출은 구현되어 있지 않다. +* 윈도우 노드에서 실행되는 kubelet은 메모리 및 CPU 제한을 받지 않는다. + `NodeAllocatable`에서 `--kube-reserved`와 `--system-reserved`가 차감될 뿐이며 + 워크로드에 제공될 리소스는 보장되지 않는다. + 추가 정보는 [윈도우 노드의 리소스 관리](/ko/docs/concepts/configuration/windows-resource-management/#resource-reservation)를 + 참고한다. +* `MemoryPressure` 컨디션은 구현되어 있지 않다. +* kubelet은 메모리 부족(OOM, Out-of-Memory) 축출 동작을 수행하지 않는다. + +### API 호환성 {#api} + +운영 체제와 컨테이너 런타임의 차이로 인해, 윈도우에 대해 쿠버네티스 API가 동작하는 방식에 미묘한 차이가 있다. +일부 워크로드 속성은 리눅스에 맞게 설계되었으며, 이로 인해 윈도우에서 실행되지 않는다. + +높은 수준에서, OS 개념에 대해 다음과 같은 차이점이 존재한다. + +* ID - 리눅스는 정수형으로 표시되는 userID(UID) 및 groupID(GID)를 사용한다. + 사용자와 그룹 이름은 정식 이름이 아니다. + UID+GID에 대한 `/etc/groups` 또는 `/etc/passwd`의 별칭일 뿐이다. + 윈도우는 윈도우 보안 계정 관리자(Security Account Manager, SAM) 데이터베이스에 저장된 + 더 큰 이진 [보안 식별자](https://docs.microsoft.com/en-us/windows/security/identity-protection/access-control/security-identifiers)(SID)를 사용한다. + 이 데이터베이스는 호스트와 컨테이너 간에 또는 + 컨테이너들 간에 공유되지 않는다. +* 파일 퍼미션 - 윈도우는 SID 기반 접근 제어 목록을 사용하는 반면, + 리눅스와 같은 POSIX 시스템은 오브젝트 권한 및 UID+GID 기반의 비트마스크(bitmask)를 사용하며, + 접근 제어 목록도 선택적으로 사용한다. +* 파일 경로 - 윈도우의 규칙은 `/` 대신 `\`를 사용하는 것이다. + Go IO 라이브러리는 두 가지 파일 경로 분리자를 모두 허용한다. + 하지만, 컨테이너 내부에서 해석되는 경로 또는 커맨드 라인을 설정할 때 `\`가 필요할 수 있다. +* 신호(Signals) - 윈도우 대화형(interactive) 앱은 종료를 다르게 처리하며, + 다음 중 하나 이상을 구현할 수 있다. + * UI 스레드는 `WM_CLOSE` 등의 잘 정의된(well-defined) 메시지를 처리한다. + * 콘솔 앱은 컨트롤 핸들러(Control Handler)를 사용하여 Ctrl-c 또는 Ctrl-break를 처리한다. + * 서비스는 `SERVICE_CONTROL_STOP` 제어 코드를 수용할 수 있는 + Service Control Handler 함수를 등록한다. + +컨테이너 종료 코드는 리눅스와 동일하게 성공이면 0, 실패이면 0이 아닌 디른 수이다. +상세 오류 코드는 윈도우와 리눅스 간에 다를 수 있다. +그러나 쿠버네티스 컴포넌트(kubelet, kube-proxy)에서 전달된 종료 코드는 변경되지 않는다. + +#### 컨테이너 명세의 필드 호환성 {#compatibility-v1-pod-spec-containers} + +다음 목록은 윈도우와 리눅스에서 +파드 컨테이너 명세가 어떻게 다르게 동작하는지 기술한다. + +* Huge page는 윈도우 컨테이너 런타임에서 구현되지 않았으며, + 따라서 사용할 수 없다. 컨테이너에 대해 구성할 수 없는(not configurable) + [사용자 권한(user privilege) 어설트(assert)](https://docs.microsoft.com/en-us/windows/desktop/Memory/large-page-support)가 + 필요하다. +* `requests.cpu` 및 `requests.memory` - 요청(requests)이 노드의 사용 가능한 리소스에서 차감되며, + 이는 노드 오버프로비저닝을 방지하기 위해 사용될 수 있다. + 그러나, 오버프로비저닝된 노드 내에서 리소스를 보장하기 위해서는 사용될 수 없다. + 운영자가 오버 프로비저닝을 완전히 피하려는 경우 + 모범 사례로 모든 컨테이너에 적용해야 한다. +* `securityContext.allowPrivilegeEscalation` - + 어떠한 기능도 연결되지 않아서, 윈도우에서는 사용할 수 없다. +* `securityContext.capabilities` - + POSIX 기능은 윈도우에서 구현되지 않았다. +* `securityContext.privileged` - + 윈도우는 특권을 가진(privileged) 컨테이너를 지원하지 않는다. +* `securityContext.procMount` - + 윈도우에는 `/proc` 파일시스템이 없다. +* `securityContext.readOnlyRootFilesystem` - + 윈도우에서는 사용할 수 없으며, + 이는 레지스트리 및 시스템 프로세스가 컨테이너 내부에서 실행될 때 쓰기 권한이 필요하기 때문이다. +* `securityContext.runAsGroup` - + 윈도우에서는 GID가 지원되지 않으므로 사용할 수 없다. +* `securityContext.runAsNonRoot` - + 이 설정은 컨테이너가 `ContainerAdministrator` 사용자로 실행되는 것을 방지하는데, + 이는 리눅스의 root 사용자와 가장 가까운 윈도우 역할이다. +* `securityContext.runAsUser` - + 대신 [`runAsUserName`](/ko/docs/tasks/configure-pod-container/configure-runasusername/)을 + 사용한다. +* `securityContext.seLinuxOptions` - + SELinux는 리눅스 전용이므로 윈도우에서는 사용할 수 없다. +* `terminationMessagePath` - + 윈도우가 단일 파일 매핑을 지원하지 않음으로 인하여 몇 가지 제한이 있다. + 기본값은 `/dev/termination-log`이며, + 이 경로가 기본적으로 윈도우에 존재하지 않기 때문에 정상적으로 작동한다. + +#### 파드 명세의 필드 호환성 {#compatibility-v1-pod} + +다음 목록은 윈도우와 리눅스에서 파드 명세가 어떻게 다르게 동작하는지 기술한다. + +* `hostIPC` 및 `hostpid` - 호스트 네임스페이스 공유 기능은 윈도우에서 사용할 수 없다. +* `hostNetwork` - 윈도우 운영 체제에서 호스트 네트워크 공유 기능을 지원하지 않는다. +* `dnsPolicy` - 윈도우에서 호스트 네트워킹이 지원되지 않기 때문에 + `dnsPolicy`를 `ClusterFirstWithHostNet`로 설정할 수 없다. + 파드는 항상 컨테이너 네트워크와 함께 동작한다. +* `podSecurityContext` (하단 참조) +* `shareProcessNamespace` - 이것은 베타 기능이며, 윈도우에서 구현되지 않은 리눅스 네임스페이스에 의존한다. + 윈도우는 프로세스 네임스페이스 또는 컨테이너의 루트 파일시스템을 공유할 수 없다. + 네트워크만 공유할 수 있다. +* `terminationGracePeriodSeconds` - 이것은 윈도우용 도커에서 완전히 구현되지 않았다. + [GitHub 이슈](https://github.com/moby/moby/issues/25982)를 참고한다. + 현재 동작은 `ENTRYPOINT` 프로세스가 `CTRL_SHUTDOWN_EVENT`로 전송된 다음, + 윈도우가 기본적으로 5초를 기다린 후, + 마지막으로 정상적인 윈도우 종료 동작을 사용하여 모든 프로세스를 종료하는 것이다. + 5초 기본값은 실제로는 + [컨테이너 내부](https://github.com/moby/moby/issues/25982#issuecomment-426441183) 윈도우 레지스트리에 있으므로 + 컨테이너를 빌드할 때 재정의할 수 있다. +* `volumeDevices` - 이것은 베타 기능이며, 윈도우에서 구현되지 않았다. + 윈도우는 원시 블록 장치(raw block device)를 파드에 연결할 수 없다. +* `volumes` + * `emptyDir` 볼륨을 정의한 경우, 이 볼륨의 소스(source)를 `memory`로 설정할 수는 없다. +* `mountPropagation` - 마운트 전파(propagation)는 윈도우에서 지원되지 않으므로 + 이 필드는 활성화할 수 없다. + +#### 파드 시큐리티 컨텍스트의 필드 호환성 {#compatibility-v1-pod-spec-containers-securitycontext} + +파드 [`securityContext`](/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context)의 모든 필드는 윈도우에서 작동하지 않는다. + +## 노드 문제 감지기 + +노드 문제 감지기([노드 헬스 모니터링하기](/ko/docs/tasks/debug/debug-cluster/monitor-node-health/) 참조)는 +기초적인 윈도우 지원을 포함한다. +더 자세한 정보는 프로젝트의 +[GitHub 페이지](https://github.com/kubernetes/node-problem-detector#windows)를 참고한다. + +## 퍼즈(pause) 컨테이너 + +쿠버네티스 파드에서, 컨테이너를 호스팅하기 위해 먼저 "퍼즈" 컨테이너라는 인프라 컨테이너가 생성된다. +리눅스에서, 파드를 구성하는 cgroup과 네임스페이스가 계속 유지되기 위해서는 프로세스가 필요하며, +퍼즈 프로세스가 이를 담당한다. +동일한 파드에 속한 (인프라 및 워커) 컨테이너는 +공통의 네트워크 엔드포인트(공통 IPv4/IPv6 주소, 공통 네트워크 포트 공간)를 공유한다. +쿠버네티스는 퍼즈 컨테이너를 사용하여 +워커 컨테이너가 충돌하거나 재시작하여도 네트워킹 구성을 잃지 않도록 한다. + +쿠버네티스는 윈도우 지원을 포함하는 다중 아키텍처 이미지를 유지보수한다. +쿠버네티스 v{{< skew currentVersion >}}의 경우 +권장 퍼즈 이미지는 `k8s.gcr.io/pause:3.6`이다. +[소스 코드](https://github.com/kubernetes/kubernetes/tree/master/build/pause)는 GitHub에서 찾을 수 있다. + +Microsoft는 리눅스 및 윈도우 amd64를 지원하는 다중 아키텍처 이미지를 +`mcr.microsoft.com/oss/kubernetes/pause:3.6`에서 유지보수하고 있다. +이 이미지는 쿠버네티스가 유지 관리하는 이미지와 동일한 소스코드에서 생성되었지만, +모든 윈도우 바이너리가 Microsoft에 의해 +[인증 코드(authenticode)로 서명](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/authenticode)되었다. +서명된 바이너리를 필요로 하는 프로덕션 또는 프로덕션에 준하는 환경에 파드를 배포하는 경우, +Microsoft가 유지 관리하는 이미지를 사용하는 것을 권장한다. + +## 컨테이너 런타임 {#container-runtime} + +파드가 각 노드에서 실행될 수 있도록, +클러스터의 각 노드에 {{< glossary_tooltip text="컨테이너 런타임" term_id="container-runtime" >}}을 +설치해야 한다. + +다음 컨테이너 런타임은 윈도우에서 동작한다. + +{{% thirdparty-content %}} + +### ContainerD + +{{< feature-state for_k8s_version="v1.20" state="stable" >}} + +{{< glossary_tooltip term_id="containerd" text="ContainerD" >}} 1.4.0+를 +윈도우 노드의 컨테이너 런타임으로 사용할 수 있다. + +[윈도우 노드에 ContainerD를 설치](/ko/docs/setup/production-environment/container-runtimes/#containerd-설치)하는 방법을 확인한다. + +{{< note >}} +containerd와 GMSA 사용 시 윈도우 네트워크 공유 접근에 대한 +[알려진 제한](/ko/docs/tasks/configure-pod-container/configure-gmsa/#gmsa-limitations)이 있으며, +이는 커널 패치를 필요로 한다. +{{< /note >}} + +### Mirantis Container Runtime {#mcr} + +[Mirantis Container Runtime](https://docs.mirantis.com/mcr/20.10/overview.html)(MCR)은 +Windows Server 2019 및 이후 버전을 지원하는 컨테이너 런타임이다. + +더 많은 정보는 [Windows Server에 MCR 설치하기](https://docs.mirantis.com/mcr/20.10/install/mcr-windows.html)를 참고한다. + +## 윈도우 운영 체제 버전 호환성 {#windows-os-version-support} + +윈도우에는 호스트 OS 버전이 컨테이너 베이스 이미지 OS 버전과 일치해야 한다는 +엄격한 호환성 규칙이 있다. +컨테이너 운영 체제가 Windows Server 2019인 윈도우 컨테이너만이 완전히 지원된다. + +쿠버네티스 v{{< skew currentVersion >}}에서, +윈도우 노드(및 파드)에 대한 운영 체제 호환성은 다음과 같다. + +Windows Server LTSC 릴리스 +: Windows Server 2019 +: Windows Server 2022 + +Windows Server SAC 릴리스 +: Windows Server 버전 20H2 + +쿠버네티스 [버전 차이 정책](/ko/releases/version-skew-policy/) 또한 적용된다. + +## 도움 받기 및 트러블슈팅 {#troubleshooting} + +쿠버네티스 클러스터 트러블슈팅을 위한 +기본 도움말은 [이 섹션](/ko/docs/tasks/debug/)을 +먼저 찾아 본다. + +이 섹션에는 몇 가지 추가 윈도우 관련 트러블슈팅 도움말이 포함되어 있다. +로그는 쿠버네티스에서 트러블슈팅하는 데 중요한 요소이다. +다른 기여자로부터 트러블슈팅 지원을 구할 때마다 이를 포함시켜야 한다. +SIG Windows의 +[로그 수집에 대한 기여 가이드](https://github.com/kubernetes/community/blob/master/sig-windows/CONTRIBUTING.md#gathering-logs)의 +지침을 따른다. + +### 이슈 리포팅 및 기능 요청 + +버그처럼 보이는 부분이 있거나 기능 요청을 하고 싶다면, +[SIG Windows 기여 가이드](https://github.com/kubernetes/community/blob/master/sig-windows/CONTRIBUTING.md#reporting-issues-and-feature-requests)를 참고하여 +새 이슈를 연다. 먼저 이전에 이미 보고된 이슈가 있는지 검색하고, +이슈에 대한 경험과 추가 로그를 기재해야 한다. +티켓을 만들기 전에, 쿠버네티스 슬랙의 SIG Windows 채널 또한 +초기 지원 및 트러블슈팅 아이디어를 얻을 수 있는 좋은 곳이다. + +## 배포 도구 + +kubeadm 도구는 클러스터를 관리할 컨트롤 플레인과 워크로드를 실행할 노드를 제공함으로써 +쿠버네티스 클러스터를 배포할 수 있게 해 준다. +[윈도우 노드 추가하기](/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/) 문서에서 +kubeadm을 사용해 어떻게 클러스터에 윈도우 노드를 배포하는지를 설명한다. + +쿠버네티스 [클러스터 API](https://cluster-api.sigs.k8s.io/) 프로젝트는 윈도우 노드 배포를 자동화하는 수단을 제공한다. + +## 윈도우 배포 채널 + +윈도우 배포 채널에 대한 자세한 설명은 +[Microsoft 문서](https://docs.microsoft.com/ko-kr/windows-server/get-started-19/servicing-channels-19)를 참고한다. + +각각의 Windows Server 서비스 채널 및 지원 모델은 +[Windows Server 서비스 채널](https://docs.microsoft.com/en-us/windows-server/get-started/servicing-channels-comparison)에서 +확인할 수 있다. diff --git a/content/ko/docs/concepts/windows/user-guide.md b/content/ko/docs/concepts/windows/user-guide.md index eeeb6bc09b2..1ecb608480a 100644 --- a/content/ko/docs/concepts/windows/user-guide.md +++ b/content/ko/docs/concepts/windows/user-guide.md @@ -1,9 +1,8 @@ --- - - - - - +# reviewers: +# - jayunit100 +# - jsturtevant +# - marosset title: 쿠버네티스에서 윈도우 컨테이너 스케줄링을 위한 가이드 content_type: concept weight: 75 @@ -14,29 +13,27 @@ weight: 75 많은 조직에서 실행하는 서비스와 애플리케이션의 상당 부분이 윈도우 애플리케이션으로 구성된다. 이 가이드는 쿠버네티스에서 윈도우 컨테이너를 구성하고 배포하는 단계를 안내한다. - - ## 목표 * 윈도우 노드에서 윈도우 컨테이너를 실행하는 예시 디플로이먼트를 구성한다. -* (선택) 그룹 매니지드 서비스 어카운트(GMSA)를 이용한 사용자 파드를 위한 액티브 디렉터리 신원(Active Directory Identity)을 구성한다. +* 쿠버네티스의 윈도우 관련 기능을 강조한다. ## 시작하기 전에 -* 컨트롤 플레인과 [윈도우 서버로 운영되는 워커 노드](/ko/docs/tasks/administer-cluster/kubeadm/adding-windows-nodes/)를 -포함하는 쿠버네티스 클러스터를 생성한다. +* 컨트롤 플레인과 [윈도우 서버로 운영되는 워커 노드](/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/)를 + 포함하는 쿠버네티스 클러스터를 생성한다. * 쿠버네티스에서 서비스와 워크로드를 생성하고 배포하는 것은 리눅스나 윈도우 컨테이너 -모두 비슷한 방식이라는 것이 중요하다. -[Kubectl 커맨드](/ko/docs/reference/kubectl/)로 클러스터에 접속하는 것은 동일하다. -아래 단원의 예시를 통해 윈도우 컨테이너와 좀 더 빨리 친숙해질 수 있다. + 모두 비슷한 방식이라는 것이 중요하다. + [kubectl 커맨드](/ko/docs/reference/kubectl/)로 클러스터에 접속하는 것은 동일하다. + 아래 단원의 예시를 통해 윈도우 컨테이너와 좀 더 빨리 친숙해질 수 있다. ## 시작하기: 윈도우 컨테이너 배포하기 -쿠버네티스에서 윈도우 컨테이너를 배포하려면, 먼저 예시 애플리케이션을 생성해야 한다. -아래 예시 YAML 파일은 간단한 웹서버 애플리케이션을 생성한다. -아래 내용으로 채운 서비스 스펙을 `win-webserver.yaml`로 생성하자. +아래 예시 YAML 파일은 윈도우 컨테이너 안에서 실행되는 간단한 웹서버 애플리케이션을 배포한다. + +아래 내용으로 채운 서비스 스펙을 `win-webserver.yaml`이라는 이름으로 생성한다. ```yaml apiVersion: v1 @@ -47,7 +44,7 @@ metadata: app: win-webserver spec: ports: - # 이 서비스에서 제공하는 포트 + # 이 서비스가 서비스를 제공할 포트 - port: 80 targetPort: 80 selector: @@ -83,8 +80,8 @@ spec: ``` {{< note >}} -포트 매핑도 지원하지만, 간략한 예시를 위해 -컨테이너 포트 80을 직접 서비스로 노출한다. +포트 매핑도 지원하지만, 이 예시에서는 간결성을 위해 +컨테이너 포트 80을 서비스로 직접 노출한다. {{< /note >}} 1. 모든 노드가 건강한지 확인한다. @@ -104,7 +101,6 @@ spec: 1. 이 디플로이먼트가 성공적인지 확인한다. 다음을 검토하자. - * 윈도우 노드에 파드당 두 컨테이너가 존재하는지 확인하려면, `docker ps`를 사용한다. * 리눅스 컨트롤 플레인 노드에서 나열된 두 파드가 존재하는지 확인하려면, `kubectl get pods`를 사용한다. * 네트워크를 통한 노드에서 파드로의 통신이 되는지 확인하려면, 리눅스 컨트롤 플레인 노드에서 `curl`을 파드 IP 주소의 80 포트로 실행하여 웹 서버 응답을 확인한다. @@ -139,16 +135,17 @@ LogMonitor는 이벤트 로그, ETW 공급자 그리고 사용자 정의 애플 LogMonitor GitHub 페이지의 지침에 따라 모든 컨테이너 바이너리와 설정 파일을 복사하고, LogMonitor가 로그를 STDOUT으로 푸시할 수 있도록 필요한 엔트리포인트를 추가한다. -## 설정 가능한 컨테이너 username 사용하기 +## 컨테이너 사용자 구성하기 -쿠버네티스 v1.16 부터, 윈도우 컨테이너는 이미지 기본 값과는 다른 username으로 엔트리포인트와 프로세스를 -실행하도록 설정할 수 있다. -이 방식은 리눅스 컨테이너에서 지원되는 방식과는 조금 차이가 있다. +### 설정 가능한 컨테이너 username 사용하기 + +윈도우 컨테이너는 이미지 기본값과는 다른 username으로 +엔트리포인트와 프로세스를 실행하도록 설정할 수 있다. [여기](/ko/docs/tasks/configure-pod-container/configure-runasusername/)에서 이에 대해 추가적으로 배울 수 있다. -## 그룹 매니지드 서비스 어카운트를 이용하여 워크로드 신원 관리하기 +### 그룹 매니지드 서비스 어카운트를 이용하여 워크로드 신원 관리하기 -쿠버네티스 v1.14부터 윈도우 컨테이너 워크로드는 그룹 매니지드 서비스 어카운트(GMSA, Group Managed Service Account)를 이용하여 구성할 수 있다. +윈도우 컨테이너 워크로드는 그룹 매니지드 서비스 어카운트(GMSA, Group Managed Service Account)를 이용하여 구성할 수 있다. 그룹 매니지드 서비스 어카운트는 액티브 디렉터리 어카운트의 특정한 종류로 자동 암호 관리 기능, 단순화된 서비스 주체 이름(SPN, simplified service principal name), 여러 서버의 다른 관리자에게 관리를 위임하는 기능을 제공한다. GMSA로 구성한 컨테이너는 GMSA로 구성된 신원을 들고 있는 동안 외부 액티브 디렉터리 도메인 리소스를 접근할 수 있다. @@ -156,12 +153,11 @@ GMSA로 구성한 컨테이너는 GMSA로 구성된 신원을 들고 있는 동 ## 테인트(Taint)와 톨러레이션(Toleration) -오늘날 사용자는 리눅스와 윈도우 워크로드를 (동일한 OS를 실행하는) 적절한 노드에 할당되도록 하기 위해 테인트와 -노드셀렉터(nodeSelector)의 조합을 이용해야 한다. -이것은 윈도우 사용자에게만 부담을 줄 것으로 보인다. 아래는 권장되는 방식의 개요인데, +사용자는 리눅스와 윈도우 워크로드를 (동일한 OS를 실행하는) 적절한 노드에 스케줄링되도록 하기 위해 +테인트와 노드셀렉터(nodeSelector)의 조합을 이용해야 한다. +아래는 권장되는 방식의 개요인데, 이것의 주요 목표 중에 하나는 이 방식이 기존 리눅스 워크로드와 호환되어야 한다는 것이다. - `IdentifyPodOS` [기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)가 활성화되어 있으면, 파드의 컨테이너가 어떤 운영 체제용인지를 파드의 `.spec.os.name`에 설정할 수 있다(그리고 설정해야 한다). 리눅스 컨테이너를 실행하는 파드에는 `.spec.os.name`을 `linux`로 설정한다. @@ -179,8 +175,8 @@ GMSA로 구성한 컨테이너는 GMSA로 구성된 신원을 들고 있는 동 일반적인 쿠버네티스 메카니즘을 사용해야 한다. `.spec.os.name` 필드는 윈도우 파드의 스케줄링에는 영향을 미치지 않기 때문에, -윈도우 파드가 적절한 윈도우 노드에 할당되도록 하려면 테인트, -톨러레이션 및 노드 셀렉터가 여전히 필요하다. +윈도우 파드가 적절한 윈도우 노드에 할당되도록 하려면 +테인트, 톨러레이션 및 노드 셀렉터가 여전히 필요하다. ### 특정 OS 워크로드를 적절한 컨테이너 호스트에서 처리하도록 보장하기 @@ -231,17 +227,15 @@ tolerations: | 제품 이름 | 빌드 번호 | |--------------------------------------|------------------------| -| 윈도우 서버 2019 | 10.0.17763 | -| 윈도우 서버 버전 1809 | 10.0.17763 | -| 윈도우 서버 버전 1903 | 10.0.18362 | - +| Windows Server 2019 | 10.0.17763 | +| Windows Server, 버전 20H2 | 10.0.19042 | +| Windows Server 2022 | 10.0.20348 | ### RuntimeClass로 단순화 [런타임클래스(RuntimeClass)](/ko/docs/concepts/containers/runtime-class/)를 사용해서 테인트(taint)와 톨러레이션(toleration)을 사용하는 프로세스를 간소화 할 수 있다. 클러스터 관리자는 이 테인트와 톨러레이션을 캡슐화하는 데 사용되는 `RuntimeClass` 오브젝트를 생성할 수 있다. - 1. 이 파일을 `runtimeClasses.yml` 로 저장한다. 여기에는 윈도우 OS, 아키텍처 및 버전에 적합한 `nodeSelector` 가 포함되어 있다. @@ -263,8 +257,8 @@ scheduling: value: "windows" ``` -2. 클러스터 관리자로 `kubectl create -f runtimeClasses.yml` 를 실행해서 사용한다. -3. 파드 사양에 적합한 `runtimeClassName: windows-2019` 를 추가한다. +1. 클러스터 관리자로 `kubectl create -f runtimeClasses.yml` 를 실행해서 사용한다. +1. 파드 사양에 적합한 `runtimeClassName: windows-2019` 를 추가한다. 예시: @@ -313,7 +307,4 @@ spec: app: iis-2019 ``` - - - [RuntimeClass]: https://kubernetes.io/ko/docs/concepts/containers/runtime-class/ diff --git a/content/ko/docs/setup/production-environment/windows/flannel-master-kubectl-get-pods.png b/content/ko/docs/setup/production-environment/windows/flannel-master-kubectl-get-pods.png deleted file mode 100644 index 73da333fcfcaae65b0ec6c81d1e43ac69d02d5b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111844 zcmZ_0bC4#_wk|wv+qP|E+UB&aY1?+cZQHhObK15&ZR2fxzkScy`<@eVzj&f*WmZ=H zv9c;FmY#}GQjkP|#fAOx;|GGYl$gqoA7C^8wEsXu{&RM*!CCxAfHf!@>T=5Frl&3Bu@NSa99aZm zlo(nBSy>oC5CWW!m>(h-mj5Y`pMn$I2ZTr*g*_QvibVKN=@sQB*QR&Yc8=f;@FqFO z)`$xNwVNs0q$`VzU2Xox`#V-3)?2i1&>bW(pw^{&%US z#r6vF-2cKWI59FV-0|Rz(Pt*Ri;XV?pMf9D?63E=&yY~5OfN#ej#lWdn;tkdSKHUk zd4C<{Jv8PuZ7e|<@MM3k0iO5jhXkG%P@m&$?hs1vxo%e|+MTUPtjR1EsiT&P!yRfx_c|b^qVECCy(9_#`{Fs3!GDo=)1<_;d`z-9u3hb_YOE84uCrm~EVr8>N>=O;Dbz${K5;~a6 z9=>q=Sa~3Od3mUc-8FBl10-B28ulH$F<`g9HoU%bppxk?EKnhV#xww)!!M#hr|Zi=y+3rwn?sbV3X-i}`XAN%slWr{6dfqp3etV36TffQ#(w?+ z--Q0twup{>U8rR7=yXZg1-i;agGcz-FS_r5O{D0j#ijOhyzPx(f=;kt{uA?N{U>4R zAlSAUY&4d4zF4DAho4m7Q=g{#D)$vPnu0Tla9`qQs-HAIG$XRdGhO{>(C59RDnHsg zi#lGYemgd)$uSC{8YYAwjP(3~A^XrCVaRqxu;ly@HZEw6?+?y0^99gK8dk*9+Bb|^ zi%zV%K5uX)-#Nb^>hpYR98Ir7_jo+6fN=!({e)>k_}p@SKl~aMa5`t~XgfSdN0T{0 zP84$bcl_VenW6UdF@PO(#KVMBN5gNyt&Z#M!}6!4T~g4D0aJA#hlRU>*Oa0!T%2++ z4eFl`Ylm+P`L(A}h3=09sK2d#W9^60J;iM4@m>?FcTaF^%JJy1J^FyT&kKiB`_}yS z%&Nwp6XoJ04H{QN&{7ZLyG`yY$+uf;E&s|JRF z`V!&!q1W4EQ@%rb6%|t}{RR!wp=MK7a{J{KYN{tVs~kV7h~AE*5_>>6m53htX5x7@ z_Hn0ivO8+EYkq-T=ky=Vs z^*cgJ`Et>=IPLedV;fZMfudMlJB2oglhBi^PwBpX^*1qQ>#)}ABY}a)y-;7Ix!YsG zvz-1o&xELHtirIT`v*v#l_&Dk6N1NM%R7s;h1Ua2v)zITu#@>n{{`7j5yxK5ZfaBL zKFOG*{&f_%?DzR1^hbHcr?k$=_XydK9HSFIxZL-PaO<-$D7?9XTGtioS{57FL&3+H z{Bf7nevSi?LDv_or8WP$KxM}GB{jD~JO7{U&i#q}x(06kr>&BwMdarS8Re)6IZBXg znu?*!@yIGQbBYQz`p>M1tK0sLDD5*XbiX9eD~20SrG63I*#v3FtKYrasX~}UR)?N` z!?jAwhVOPlMSUTFhbLL~*W3mSCv#J*3Y%YJza(p#bgGdBNhVA=$>;>o3a)rFUG9f^ zL(^@~ZuSoP$MTm2YK)G3kWq01m6AYCkWq)ZC(MX`A)pSEyY*iSUU9S+I&wA|7*Ps5 zR_fhw6D%tDcSAcku87OV|D37$(@$K(IEtCMEU`d3XnAo82ovHgvl6(!5W;Ih577lvd4km z2~7`En_=|qDD(w8%Q^$YQxx^aC_ScaA>29aSse2ztr)@uT08 zpuPJloRcoHd`J2m(u&i_2D@|2Xa{fkzb3zS5z~0ld*#r8_rTCnaZ(az*lEEbra z+WGG|RBvPb^9TT2r4hN6hOqgca+E5@LkXx1A$#&OUx=FCo67U7Wh$(Nv}VvConY5_EhG0YSwcP6j1UVH*OyU1svgG+autz1qsumDD0T%VBi z%X*~8qNZBRntT58U}6*8u;LH?;RL~9*Hu1VUyB-xV*7TroSCC)@?aiN7E1`?b1z@_ zkzZNC#_Z$dMA;%J8R-G(!ydy>JzNq8=ssg(p7^*)LF2FJEe1Pon)}T!MGeIYzA@kl z&tpqdB=2l09$cC{cO@kihn0uq9Q&v7XbmY}Ukn)XR(<@+72(Wy2}Jv1T`VB;5{weg z->bc&5-mPSfl+Ep&EBW*3VFpi{`e3DAi;A{)pHwTnMk5W@NkmGZjfhx2|UI;w-}$a zEHB*#WM0sPJ~LjsCw;2PDJniyxSKYh=*iBO;rjS>8ulgN<#Bw^EU$$%oZB|)`ib98 z**I6qIaj<#c9dhjes0!xxT4#3T{-CRDXXnVf?#3oE$IMuz)(<(ZUM^ivSoC(-rm)p z%m4j-;>Ll-e$==V*AmM!*#G(V`_|_8;xC1jn>h8cy&iQ-@9KjYXA08b8m$&-eD+dDwznpCo53DZnu`!R9f9gf~KG5{3GOk2&>6U0o+IEn_&#y?O3gh z5=FNpt~U?u{a{)p?E1l!xU>m@6j~~f5@Lp^p&jgUm3USauk@RrN!f6*XZB+Cey#t3 z{}CB%bvEOM+0pjca{@>-wK{X?Wv`#(KyErJ;Jed3LpH1yVpWm%Ij<+VwXimVZ*ajd zT#;;YOP6YW+#&56d8|MV)8x$QJAl>Tu>i=5R*|A@Ve~gDg4OKzX^oO=c=)MrE|e{~ z4h_3jnepn<%CWmjZG3E`L-5iBZ(OnfheNK14it0t7A18|ynCd0*!5 z7Sv$TfFP1Ic%*9RZhz{0ixrzT7o8dA;|o_-VnQKLeBE=Qg>PvlOzxi=;g?04Pv4HR z+iNMPVmz)J*0>Pl9pAP9E&f3%&GejgExyxARsY=|=qR5k)Xm$PLF=Wu_N%)46PTV< zN^DjSYtQe2^rf8@W;t0q$dkq>{FiR^a9^I#1))(4CB#Rts>fCGZhS*S`Kn54K6C(| z1Fovq6AP0(gmmU8U}!$<3TZdydviAwG768ez*ZIe#P{SPoyUZiarUVe9f!Vaep@#x zZ})*7aei!(QLMi^c^KL68teAFB(&Ym57nmE@rrIcAXBgI;QG`$-e(}K!O94cF$+`N zmS1}60isy>Z&v4E+S{!xw{Z6L*8>z0;)LUgQZlktSHz+1?$}ne#Zg9yoj?PJsALj` zw>#L5@BMH7*5zPAywHO)@ND6MX3N%~;pC?to7Kp3*TQ%kS^6kQkl-#nDK6EOqLBAKG2y>W1B{FizRQl`D`M z&j>tj;}5XbB*r+B!xu%A@hHoaIm%v2iPD}wBTGr@p;Sh&0068vEEgTbVfBuRvWESdd?I5voT)C4>5`g=S2>3(qTgfwDD zHi)+1IFOll=v*8qmBFMJ41K;`D!5sKuA9}KPAzRgT(U>63;fh+AWwX(WBlWQ*s3M9 zVK73}8bJr^3lxQGxaUJ6@qXzugmwI><=P=rCqahgS&0NOUsY#-Ul+RS3ng1dSwO8; z6G^Tas5jdaTl3u|O~BLwfu8A#5&_+}XZ^bWS7cZmyMPh#K6QnQP)zzbzH3agxrUo} z-@+RUY4;QU+5Krq1UH@=j@JYv)nECfO&8s9U?5LHa^ty89{6uZm750|TZHRJ!Y_0X8i(;EPm9wx8^M>~KUpMkcPxX6Dn)c(R-HX9 z7dLfrxN&GA{yWSp)H_tUEd}(1tXrV~vyi7dHz*N&1eH?l`q=W&{|?FjUP$PYEL06e zSD^A}Gzm?5f<88I_;JZ&GjG2q2qwe*81Hfsp<8|0`CA^|$4olQ6+JVjdQ)w}`m)Lp z*-0>Now{N-4;_Wyob|@P@tcEx(u80(RCmNV?ye1bX6bLFy*+fO=KQS=&4=`Y^!E8M z@PhsUM!(5xHZQUd77N}XA?r}BCYigx1MNqILg;dE2g(j zQCGt0!y3~9;7}5u%jnW0t}*e7>WX{KkIRxcei&Tk*vBLH@xUX-W4HnSz|i7^;+>n% z*Q`nZho#-(aOZLb1sa9I__u|mS0z;vLLbTpfF;ePHtl7@_6y59f zQM-C}P`}j*p$Df>5TDx-nXMI};8P4;!0vXGzc!Qbub-TDeKeqWz4zR$FOT`#$6&_g zQD}lHXO~1MX;Ich?LQNUA!H1~Iw|M2m2 zTz-L3_&G+wk}D`T1g}Rln6nH0XBE+)%!Tu7+TN=hLx#n`vtTyItDqdG#kERO|lSJYy|V$l=Fk-f)VBtC8}upU=&?9*F;X$kw{12+=9VLw!u~4)s6jy z>V8b?v*9>lGziu4cLc+|ext*+cvBY2cp0U+RI{4@buwqjqNf;y2L}gfJDNwz z@7>y?XHTCRX3^oWMq}?OPbe_e@^p~d98sm|?YaiiX{HzQfl)KG?m*h->e+p6#e@Qe z{NRIcW#77ueJ_Q<`|fhn=Z*yiK~7PnzWD%V>%Bcre~HefNj`|EQV7()v|1ZNbrS?# z$WfqI&P%@iax-0-S*-5(laqVsFy47vQTf*!*`-GhT3o$+;>`ESO})#r*{g~lIxUYr z2R@zTH7faZ7j)mZ6>jV22jgY=IX9;5*zZ|GrD5Q0&*oppUDX{3 zdIE#t_0`$|r)|Qu-8VXQp{tzT;;F@i)}EZ@FDqz^|ATCLaQIpc8ule+?y~~oMd69q zOriO&2nT9y2|d`p-Q%)sqNutJTEZyewvab!X4(7jJvoxaPt>?K)`!!l%M(X zR+$kw{H=a(Y4paXHD<7ndi`TU^rvcTKkCPJPdDRQ_?%Y1NsmkBcSm8}sr@XbAGI!| z1FeZ5jWwpDnSNS;W90%dgjDOYG_Ek=rf|Wpsg~nx(r!RB(_KQtV{$xAp&a?9A;gCE z?C$=@(fy&~f}3&Cd(onT_Bj=%2}0~#*cMxV+;}{`^_><{GQ+Bm^iu@YOyy|0$=)p4 z>&4NFliwn(h(nQM(F2$2*9RM~#dnGdr`XG2iyB?nF#+?U6!yAWrT5i%PGh?1X}u8hDA%WwpZ_GSljI zLJ*Scb_s}_blh*$#AaJCjX~uQ^k4UTpOoq2XOAE#rfC^Ll~Wtr9a;hV7Czq*SkpQf zX))5EAuSy)^5q<(R)`Cma|xj!C!;C=!}!*Ti^a67GIdni{44h9O<|Fd8!&$4ay0T+ zc{eGhIa+CW^s(svO7!gFs_2^=?+P|>aCFkk++hJvo_Tn*-!xWK+h3?sJRWAo0hiz< zxi>}yiKD?+^igAXA)-EvGhJmJ={@H{q3BsV^N*6d3*1iCg(%jrh> z&(YBK*hukpFkZu?Hj<=LAMIZq6cozpo`4d1rw=Uyv_? zFSNWnDFFVb4L#Y?g$XhiQQV^o6fGyAn7um^{U_quI6VHAD&&Rud3a2nc&$oFY?}-i zdl_d5`P{-tB=Yp(Hr)#D%*)Tfcx~FU~uh(dotK9$s_KRBU zB%Xdg=8~4_bWEd>U)ndXWmm6j+@@t^j(5&-5yf!+pk!r@As%?)+()&fOcAA#i6~@nC`&60?k^pSSRN? zS^x1VmGd9)4RO#BF{~)X!RVvl2=}wZ4T%!?(F5)XAKLD8YE^$EiNmY|v_Co^R(`}u z7pxC)R)Kb8r}@T8fH2#jAAIpj0r#1@3!_y<_}#@dRcnkwHTGw=Qp6g!SqO9`rOETq{tfUH2taQ zr`b2yX=Wrmk`=u%X9$DgS{c-|MQ6%Givw$@07Ne|*NuSILrS*G)cCs_W}ABh3^Y1Yw}}LS$Vw9N;tR*I?Mu$)OaxeqJ)#) z1bKV&ENkshOa@kCCp}vrr@lFBE-wS%!~5xW@q}HR@!Z@k_n7vLi?OW64&YB%$@$}L z89NQgyB<9IYa`*`hg?1D}I43Md*{D)cU{i{WN*IGK5Rom205*-@ zUX+M35n)Sv!y|)>g%qQjlIhkL;0w%b=o!@!UHu}nm_N>^`HOE#Ik&r=3&Q3bzZk=@ zro0s7TIKDlP3){;Ed?)o9CJFyTNq8bhtI>7W;fm9Cmxh1+m_)$FvC0bXO;Yi;H zMj?}R9<{SF6bcJ@bDwiVyAG?vJv}X|Dpl8;L<0K`d=>eiPRyO(T*$wDda8{stvAHRtlSeP?z!tX>MXKT8MY0*)x9AKCfq$Aj$L<&ItDb?R&=Atq zbLG}N9yHV!Iv85N=>%Kb{VfT(OXumr9~&!840DPCq%Nk=RvHp#L@5>Jei=dz?0v`8 zL|sJ2z>5N1aO1$EXE$^m&ZlBTa)zmn33BH8EZcU2+weA(?bv5ua&rK~m5sV{OKGze z094HnLR9?dY1GO=@868t9UfSdvOC1Wz-GD-=CWygC%@6+z=;J<0A*A|}^3P~jB@T~^^!z}@Y zNQG6YY_2j!;hPS4ZGxw`1?p85W75lnEK54vts2)(8tv_EA@uM8)m6kX3lCUH%Gh96 z?qAd2U1baWZ)51FzJ8lKv=xCiWtR4vG&TViP7xWjXgeIRYAwb{5X=-=08%spYaWAX zfk(-LzAES=iRY*;C@98o>8`^l*4EzQ^GC{a5Xkb#-IheQn`%bNhcDgsv6^ z2-bWOqprYfPCP!yAd8r?SaedJpyIZW20^7O;Y#pjv{hjL)blk3uk z%=KPSbEIbzD=Z!vJ@NpWFcEZ_wRt{ulQ|t*s){o+D}B(X<;1I7AZ-D--8Hi^1*xnE zI48RF-8XTsOXY$sMJ+ZzDtL-jGvFW+dDQrD0y1p2DN%L4OqT|O^*&pD|+A1f);

?hmWu|brK@QlAxTn-C@fl#g22{hOAF^6 z0KgAOwKX*Y{fHlG_5yQhZVL@a^e4MMZ9f@-^Mx$w6+J6|j7=Ntpx~v&jBr$7x8oZX zi4!B6MA=XnN$%#+{8%h$r!ALa;#v&R)+TJe&)FCJ^8+xu8)LBPH@+8gy03FlH@HgS zKk;Bu%j5LXEKsd*1^DlzXa9L*KscTW70Pht>&70Q#vo|f!Rpki z_l4s(#-ag5@YO5ng$JNwa7j>f!I@nOB$$JHJzbnA5A4j6(c(ZPaiO zbSv(SNi4Krk)J;&5`QCkwYpu z&w=*=9`_NmKP(U%6OD{r_DyR&u4^2JRu)0LP02SBRpSRbYQt)7X^*+zoJJT0Yl#x} z_40KQUbt;JupcXVst5X0>QSWStlSAap{nvwoY!oodOdJ3>ANy|FZ-_)uhYBT?BcHx z0AC?p_Fi^2G0tG*x;yS7mFCf5^3=MiJ#R-pAkSUAxUcx z$YZIQtU>crI*J8#U+Q(XwMHZFOS9wci79T{vfR=B0)7 zy%-v^ZblvSoKO@39JiL|o=azw?TFUZTxrN|@@Tw}SxV|^VKsf;B3G-o=1KE?-d&dS z%u98nTz)an3=-YnI!p+9jVBM|*^RHSmVD*Y8wLN_Q&Ih|K~2zD=+(nEIyCu8L+)Ww zl#^C}_B(h!ZZiQNiMaUDH{=slSp)X_UFA6m#o3dJyh!aHb(w)cZ03|P6lZhTt;kR! zR=c4fw+6vGGqvSh(j%#iYEh00ilLfJp{RNV68rQb8vooSv6isTxJSYj3OE?_HMQ@H z3LDw>mlx?8rgmmpRsQJotJ0ee#)Pq9GGuf*?%g|lI3yAiN;nWII>%`8`!?QZW8eP9 zoaW8d*T}$AN)GW zD?NCGplJ<{_KP9RBPt1kD^8hy>WZM3&W(8aaTF$IWB`x8)?hkM{ zAcH+oz8|d&NbsWOoqo0A+BqK{l;NnS1(6FP6(DAEsOA`5wUBn&|LFPTuqcQ#6Ovbq z3%PqVnE76 zvzU_56%hizI=}?f?Pd?{saj@7j^)oTUt&|nlw*HJ5lUt;jwZ7kJLJPm*RUqUOx*`jF-H-LzE@(LYRuol8#Zi6&IEJuu&uPUCJVP(>r5c}Pdt|z{ z&6%$Z^s7J~(d$QVG1H0sW6BnZw;t?cs`o4!ah4gqZ)v`FxDRFUBBAI$wp%IC5B2~x z5v-G&{O?ax)EJV~27vVocm4w`yJe%$9+vm}-e>Vkh8 zUqa+SC!~&zgCgedy0ZSvZ*5JS@?&|j87pg2)A5lyo^#XCV8q=lHI(^H-f4lb_><`LpLo~3`HgL` z`}oM-%C`aWNi3gKuvd52H>&Mn6;xm zX(FmLR`1F9$IAM&)c2JFeO?pt8&k`zz@pIO);rx%)W{)s^yrE#b{H8xPKA-h?z9K| zL7#v0QL!brbhL9HGo?DdW#fRIAjpQGgx&_lf7f#bExOF zXjU7@27DFYH&kmZm$UWxb$ZI6LtQR8`XXEc7oP3AGK;+U`-?Zu9q`N2i2RT>A!g3*k!07C?Y3A^mq4%o% zPaENYVf@~u)q7Mm7+(yuuH}7^XAo=sS*dtS3UMMoeg}!?d(;O1tAl#33tdOAyF>K#X**mQE4rQ z%=^^(Fx@~IzF(5)v7Pdl&1U%h^Ugk~pl=Ww4YX8GZZ>>~?g zUjVI=I6V~9UzR!4;QLMsdOdy!9G8P;RROy_H)HX%sh@-W3XdyG`HkD+QTH;8;b$nB z86jGyisDvKn>?R3!)y!h9XOQf@5gWPl& zl`qx3+iB zBT)_xZGQKi7)`ib-_2;E)I$2J>77|v3%k0a;a5d6^SLs89s+W8R)w)H+zY&gH?%`L zD+Nc}4r^}BQ{kiqn{9<-aQ?h&Ocj7;zlZJa4;i-onAET($)tqycAe+`e zXvI!oU%y4R(~b676;<@(j`=1Hiya5ARjg~iJ;iVsL|pxl~q zFd6gtwr_mxU0Ey9P+iSU+s5)MqE+FQ^Yn_O=uG7oX0TuBTsx{J)Q!J>(GBF(NJ}l+?Sa#% z(+f5b=m?7wA@Jh0s=wY@br`v-ym+ao72wjk{_7Tlea1$2EMmkE)V6VcBAQ zafn2Ey>nxH?WwWfQRU-#Jh>u@wdh(&WXQ%9L%7qL<8lV9Bq(xKfR~sJ!lgg9QnEwbNIt?zaWZ zrP-V)@!fZtuW?7Ujkf%vBEpwiXQL~OMhg;YIgN+gb>QkjcDKh=_R0@y`;az@%s{GwNBp;F1>DWgU&-vaK$ z)z3!~-Bbcx_EN6Hufi0v+s2bzB};4~RHY{a}LD%J2U}zC-}}RM&^!J}8p_Z(dnHZpol_WY)h4a)=OOVO8~e zE3|Cq{{0&c;mCX#N&sLJ^w;2%_xf!G^Oug;8KUZZicn}?FOuwQHMqWGuen*cKF)e) z8*W@RAKt|(e`F|Ey3{5s@3e>QwztJhBPlC|QZ}w{SGyP2_422Tubn-#mCb|o%YmUM zf!}>w(O(4bJfJ|^PG%H#?0S--udl^am;gY1p?`_RB0zk+NvZFGz3_?zznSdcc0&>% z02PG2_&tf*x?PDbAxDyOUhbcK`!0rO-F&h1RQs4rW!SGj&ku!z{tslC z>YwuH4rV_!Ln;VtO2gldsFua#E4$g$rt8zpUvkr&(iNAToYe%ld7HVwzFFf84)M89 zg^<}b+q7%(FJ6uG3J26uXg*YU5aIelNidD#?gPkMm=X=x^A{944ALn(^0a@&-NFds zFTF!Zo~X_~C|wav{(69I)sL00g>PAnOUlMyUukG=PgG1K(tzDWQ}}6{wr66+XPH|o zQIfhlEPVyIof1L1Y%?r0#@JGT?XhBIjicTz-aTw_t!8=Jsrgd7K=Zm|D_US0(E0mJ zb#L5grWH_n)NM#%i@sbpm%Mdz6SeeK&_0f!Z(ABzT5W_sUOVH*jeV!y>8u;!y@wm2 z3g1?cNZmw&(g0n6J9KpUQ=`x3jw~iuSH)#%*uh|#*&Hjw97-Osr-n@_3+*?nl8(f# zwjCYCA7!p!tTWN6pYuLAcd4L025D$U=pI{3GS7~EW>`Rizl#Tu)^QfWgvDkLZLZK% z^Y4h0LUMwFd_7LB0Vx+KFSF%R{f5E27y`2v}* z9X2E_ttD-*@BpRv1A)i45?-qYu)b7c?%J^VxOcDfJSe|Nf}JFB!-&yG#`(x-A5*-C zy{C=uOg%sMkVv8uaoS(;1_Y^#L zSk9p8qr~55*9VcTJw`cXLdbGnBdzv_g0c89pVwP<7xvc{$4hE9lAFCz)lXiB!3MeRNoA zM(-f0h_aI)zVs=3)5XiGnMdF6J@HNHBu$f(Gd|}9ewAC6B+N)1^eYiCi*sn5O)?8w zWHre*V9>U~eiip`SDOkp(8MbHQ=p`4E@aVky7W`zv>cWie`04|a}X)RV;d3D+v+q* zR&JK`jW2~sXx)IPfB8)Y*+>sfL;(Ms%aY)XhUu5*uh-Y=%xy?WQAB?q)Lu15I=JG984pRlTX&l%lAavRUbH~SD~ zpLxdvB8?_z??BSQAc!eWFg05N-o?E-}EYh1Go7dw(*I@0yEA`{=_2*5Oiax z(GX1rAl{E?xiKGbu4GpNxEfp3f znO~S^9cak5@oV{u^jX9h?|^joTVk9@Xnri|_rrD#8a4y3EAQ+6b4SsF1DD+m_S@>D zgqh&B!YvQ_@oD<3o&yynf2jgwfOBD*a89zP$jAkDGm{9Pd>jCwfWBMvJaQkaR?_(T zraC5yCfh~(qtDWbzG6LXmjcLMwORM3aC=WVxzDx9+9osuG;F+K2yvlN} zhPjK~S73Vt&eh5N6g>q%WJGTz>}r_eYhcORau!f1YF@+z{V$l)gQB5k3#INvIOvRI zGLbpsjwzCa9v6K~zfhVy31^HbPMCt{#g$-bm;7sjIWH)r0e7Q zce&dN`S7XaeEgwOD}2poeP{DkLIAU^chVs+*lLwdDKuL_ezicxzQ5s`i_?DQCOQfF zo@W=S68}#Hy`czn_E*qDNN0iB|37Ppn*;iF$Tl}~p+)6?vNQho3e7lxvk$z%6A9P6 z{coNAZ?6pVA99gk%d1t1^?%oj{M(}bx6Iy$1{YsO3>`=hrC5~3!E7n!cX|)jYZsOLl(Q_mft+kwQhcSiIJX)6Sfr& zl5D#b@Yy{zedln_B80Wbc^4HL@3kH#A2&W`5S$>{Bxt- zNXQGy=GL7rURg1{G0ku!`&Y487Fd~NE62Z>WQmDE&d!6No*z({2TtW-?d-7)FqJ}! z86O0w5%I6*nvQqB#N1Qzb4=QexQ6noXuw!#V5mE}(R%D{`}Yx{-c5;JhBvkL}DnjgRIQ$^k0&}&_D%WX`Z=oHGhmJ-fAKLim*< z*oaDBvFRCD3zED4DtDpnpe(W(a7L=5ld_s33vBKVfY`NMyGRb9W0u@^tBzwqC9P&m zSj!0Y@cU4Dz8YO-H4)9AbQjDZ50dBvQb5dy6Fn27W_=+({<0Z^1U+_$v|$!RSlf8T zUwO+FRU;hlkEW3(E;b>D)0PJF(^s8Fo_g7cD+Ku5Ji8+Xi<0x5vc?#+P2ms>yagZA z@9<>m+c-ENdH3O)Ifo`d9*mU)uFUKZ^T^mvjR8-GPTKZXLPz`4dyrS@d^(n|5IgMH2 z9G*@wNh)6iY}8xxy9#0S5N}+?^TO-bJT)B;W282G(Ch46^1F@V7lS}5%nfEHh(Tlz zH|vddFRU_Z$Hj_sAGEd{q`@I;I29iCQIil|uWf{-BSOJ;CJnqo#(tC41YBu%z&42z zFuxwzfRt`4Mf-AWqi5r|>PYuzW2_n*b;A5(aXxDH+=hfaD?8K%H};_C)NG%*c7Ta! zN&Q_<_ne{kar2DasN2XfD>wNyOK8wn3?7PNC0dw-qTvF=*h38l0rMM!sbi%pFG-)K zzN`@H(?>OOkKgrK&d1V`TH70PA7&$`blL+MGwK+PfjdiOcAyfEQSxMdRk_uksP(E! z!x4lPC5;yWYsUdG6VX;ev`)i89bEwaJgVW6HCB{Tvg^tBmmNcB2_UEmiI1Wf8R8-B z@V*LGT1WEsIzd0)bUay%?6AAaaoQ>0Y*N;v?wA?E9O>Ysy8i&;yxm6zdgDW^zX4Z) zDRYnhvFbk|!U$4f%C+Rkw<^1SiV4JFYBv|S2eA|GDZQZHXRoC`gFroW6+Js7mr)0D z`fl7+eN@Dx!BCy5qbEvPE$G;5TWm^hI#YU4)|sK>DohfJ1>Sex@s|=*A)?c|PGmM` zW8{tXQ?y$6Ii1ZwFEBTCx1tgb(0Rv>bkBKnM+5`cV^@Nsb4WnpR}-PhFV>T~ZWIk% zgMM{8rCo>g4_)S=1N$?aPkCMHwc%ogu|$l#!Aop`!bed#t$; zlrn1Q7zL5?tmu--SOwRv5YA*gppnh(Jq~D;AT1mV1Qz(~0Ym5XQB;M}JsVRgcnIa} z@EaYY80iB5JDOQ?lyqu6G#3O4pAjVl*N}QATpOqro|PFj>m!KzM@UduN7!K{p^YJb z&j)8=kXPB=15d`wg*kyKR^d;-=TX#Y2#>UZ=qE3mr~G+Y8bFAT4P7+`OmK@QELZT1 z-g~~e4U&lcrF^iykc-ssi?+Ix8H9%gmN!`BZj-NaE}t*F4N=*l6yAv*w>}xqap}w# zF{RwcbT%DerrVx)$0|uR2#)ut;IFfxB(ZL6kBmTlBs%1rwjW7{MKUoGni349{BVu( z$jw9eHy+=6rksgR{31~M^15{pEkWFC0%k6XhaFVHIbDWHB$#pG&~R1x%&jMO!H$tV zgo;GaPC`? z!+wSscRX$p;qXOI*U)0|YA|)dj&`H_ICrWq4DSKs|wi#(%hN?0iP?!NZECFI`OO`ne0|U$*1ncw1 z8(GdFWBjAoOP;K&dmppO%z!Yy{ROu5ZiDe&VT+$b{RvcAyvBOF_ku;TzgHkvW$cB4 z6Lb|=sYZgR^#||D>@Ys`{%MLaEmqwE1D54(NC)I#xX^MS!NHLHEC~$J4XDTik`TVL z-|ie*-;EupU@%Q2xE|vw{GN2sv%|@)xtG`VjXB$G05R}0WuyOg1NK8hGMq&l2tyKQ zx7(;YHXzkR!GlbaGrNa|mMs5x@R0X3 zp086qyW&RsHr1bYJ?}e~*RTt>gt~E9t(OC;c$0BjRRg9Xga%e&1WW~FygrvN1==D! zxU#qn`?b49Y@Rq}iJ|QGdaGOBe7PTpQq&5-IX$mse2n&M(fhN@1@#*CoOuXx6U{;@-wf108^^@Pv zclN;wNtC*t{`=ZlbN_vd5h5W@YQDpM#wie$!!|3bc!r*x1D34jIBgbE&bpF~2kmpaVh5#(I_WV;?Yr*ilZ z+L->1RlQUXd=oU3-&;yqQ0GnFkWMazK#v5ye1eJKS`Tzzang-3nN8}Q+0Td_~?uUlfB#)2^#GaJ53<1SMI!2cKLBT`! z3P*tQQ#KSLa}lvu;>;|oJ-03@r^9;wWs2jq=eoA}Xm)bb^8pAUN-(NCAK0gg@CXY@ zy{oRZ20ZHQj8Gajni61Q;gqEDAdjZ!Pjs0tCno(ZwOB4(zz%baef8K*U)|WlGGR0o z{`=(n%WLYLB7{W)>{q3c0fC#rWkX!8xrtyq8VL zv{vkPjCgv+Z;{{nl#dgO@tr`7PU>1O7j{zA7lLDA+axhrj^AWw7Ax zKDY)A?i$?P-Q8V-YaqA=x8UwBgWKTtxboipdAGXieD%*c)u(%RuU>11cGF07%l-Rf zNl0(ief}d;x3ri%%e06#i={l%*pTzkfrT4ZK=;CL_}SjQ2dF@vc|t?|e$FsAFxH=( zEj1Qx6VUkLQT3cgl<|+TheE#%<8iJiG=4j`(;U5~Beinkw?J$f7^B&azH{J`c4A7O zh8bTuJ{c_W-3i6IDSsgP>uCZ4V}=SP?9G7utA_U#q8j`09cdRgb|lPVJVjsG zso4W!Tq(9dCx^SAA3=5mjTBc_f;?}oJ8vU98c|AANd4~gLK{lE1-{;@^&483x)zAt zjIin~jFAJYl~-Uesdw<)ikFPc$o^oe8|Hv32VLge<>3@|L?cxt!0+V&_)_friJ@y~ z!J=^|X9(C=QYcwBRQf_lkfrRWW=5yw-!Lp?60M2@|JC7fSPEZE!Wp?j23~1#2|11C z^9WC?)Rw?b#+DqJqE>lzV~^aY>(Xx|0bQT(R@A;UX>U)7lSSHn%~{l0_nT$u5=W>M z_XiqdeSc2fGtK@gU`#|VbwQ}QwSbjuDE zF+L{oLn5^8x|EZR7g)l5H@_Bs+-U;_JHm`L6r)T)Wd_{e_w;(47z2k!gd8JpX1Gc_ zpkBv)>?bm!_$^b02>--0gLj=0($+#5XH;A~1o2m&6XLVNf)$^b09F)o%{gkxYRmDt zctO!L5#b}@gF+TWRk4cTaUGoqpli^b=>Kc(wlK*_vPH1}%orsk*^1dI6SdI{%dYUo zcSVw3Wl+mniYcf3oO`}p`puQ;fO?nTe9dgh;2CnVtsvj*|1S@A@uF0s~dIxrL_ zHK5H7iSE!C3%}?NV88;C-CU38LhJ(97lKpo&^}lM*iofah32vn_uNw7IB~8b2DiOg z@*hv*+69q9p6Q|xkw>V5BwXvNb zXyOCNQ($Ec4b6rfj%5m+S&GRaM^ZP}ww20?oV#Q!$_HdwSj?qPp=#Swk7>dVGk3-4 zJvp_AY^xyDDMLA_-A-BUczH+^s{sY?|^yTo9AQ4s$|ic#4k^*5234Z=v* zn96Ro(^2@uP^uuB+6vXUoC=B& zzfvMipchC4_rnyJZ@Hfs&k5Ol97E-0W4l}-TI;kZ50h4#|5K5ZgoVsvLwRTuE^xW3 z7qJaI+o13eF;zC13jHdGb}TRrvSSj$!=(-Mp2nUMXDtJQi2ZO;1^%&?9*`_*1mrZz z&n<%mi69{B?dMualai~%J|wPJ;uEi4#bnH|qB&}~+&}r1?f_bb`fYjHfnOeV51(!l za>tg~g2FEEb%|AKT+Dhs;!06pQ>9d*a9QK(e_!prZ-Mx2pbSbOTbaDsD5>f7Hsi(I!gLm_418`Fi(IakLJitw9B z$?}nIX?`x8C`gSu%WZorlMXG_7WIL8NqNU`k1B(dTO!K0FH-zfJ#?f>?Gd2SO9ORY(Ek?!J>h*sRWBj4Js;ZfijdExGSi4Sq5^nUY@=Z!&>4F#Zu5{NVdX`TbG-Z?|B%rP`PF{|mAW zn&Bo#jeRMEAJtM$_ka;ntVkcuS^8VM2`=pu_P6{0CaLYRA0o zstq8YuOT=y_8Zl5utbVYcSJA2(G5PVxk=r0YQSw@Tn~ij^kR-&XL?~TVPe^Co&3@$ zKK_2H>)xN{_YH-f3Z<-yw9fOm5ddPp>sB1;iwlPP^K~tJvl&X8=Hc!_AW$O?H4GP~ znL4e`GZtpxc)Qwo9Ixlk#N~|Oi~8*yj$)_TE}k&-*Nn{yZHYTg9m~m~+k3wN(4=O1 zjfA#UZ>s)FFsl*G+xDaazSN$YOwUVKb!kRi@9psmKB29V3Chs(s^aY_UD>+?k}Ntq z&ytkavyikXsEh#~b=!R1_cn5<9y&&@m6|Ru44Iney|HV-ig$ZYMv|PPCAJzO{qQAP zE~KU9NSxh15ox25RIx*ld+Fw)ph!Nj*(*tXm#{&WytKX5vSHh-<);?{q>aoZmjgEM z{T#o_iyPX{^E8jT5)6ZtYAM6eh97dM6Z&Y?@mI7BZ@cF1K3jG}M4hT{#mflo;D&;B z^BR>I%;>Ci){seV2c^cVg`& zh~ccv^9qH1gNyhotE~eH&SzaI**V;9I56XiyX7Z=oP5Xbg}tr#RaaIWJ0CoasV%zF z5kU|r)91ue@n|`+v$~Q+y%~U5-Hzvt%I!rT{*7DX#CPp&FSc9t_h4%t{$V%G+5d>G z7|b9zpT9tl(tf{OZEml9u=+bV+Tf9HQKURmQs5?^uZW0x_eN@qB`z1qVgDeeZZxk6l>_-0z+ zaD9T&aJ}52Q4#Z{b$bVz8V!3s{7+k(Dpi4Yh?v~R2H|jtDU_$HO<0Ub6TnFzT&0Ur zYzq<&{qR7R9Q*VweCtoVj}Q+DQW@#wo4Zp|^;wD_!Jj(0MoZ!rgKjLIPbxYCRGvQ6 zD7gDt;Uz+Ma(LjpEeO`aGvR+lqnSM0{b%vaPbO_&D~i(h=%c!Oil_mJZrKg?!zc9d znl|XfkBHXb2+|=y2X=?d3E~N$jw^#nx>Te?A zJfF0~vFti@{k11@0;~2I?41?u4%P*Tyqjp}oF zptly^|E1+mp>Zq0^!qKXtcI49xSqakp-t$zVq+NZIw)^xGH)B`9jhQqW+0^ev#AE=9^k!PoCvbjP1!4 zPUgyt-_VJTolu*5=VKs=x->tNC|x-O;fjjZ8txKSfvB(?c(C_oLuzwhc7u&3WxTVw zBjSuDOkb>1_kn3lKoTy(Z(K0~wp5O(=Vohp2sV2;nAg<;DnoBKSSE0 zN`au@Mo_}B!hGi+m$LO8AHBPCngIhf_KBS4FNZk3{zO>vPw4RTW7Tt~ue!T}+HX~T z<|M)HXT93mrrUu$l(xcZ2%#n-OAprY10^gb$uSnWa~wSXrwm7ulf2Ixx`uPprM3+u1)(Imj|~4wiBRP0czfjJPGtX zGAyh|)U3ckvWa4b)4!QG0jrLTqUmmXT#T9j-~=_a0~@==@$HokEK_xJK)*~b-AAXE zaz53AfH$SU{J(#Gn?B)zjT{s3wnZGbf8Z`{Sw(s;f`=;IPZ8K=i02!i1w7%_e+f1S zx~O1@g2KG1;Nam~;__h*eyP;R2D83W#JpkWh18&OHQ7}3o28A5csC$ID~%m~&GtIE zD>!)-+%1>WGjvx$+;(98W=h7_8vs5^BelRc@7VjkwyAiCiB3;ULkdwcHxK3jA>QWR z#PbLcDvhu4t;nx>=;J^nk}P|xlU^U>tF+&+y#u>i(~2wc=ZRW1lGOszafcKygVNd4 zca`I@ib*^VXm!}x%2tbtr!Lu@Pi&+NnVWr|1i*p6s4EU=gqNS6xPh*WmSvDq6cIG` z|5+xd5$hfhGEg0Oo^~9O5i2p-{gYvOYE|2VeY*Bwcst}IxRp+AGRT}edRkfM=sJbc zb#JJz&X;)mJoO!R9^BtTTOt+wbI)nIl^`sOZ)$3aV3?9Wsqd&;34hUr&0SNSYd0)A zAahtKOdf22hU$gaWWyi$)2ZxJWVECwyYWS|iffE|SZtt^5om@S6K+1|vy;plnm+xr zwG+?gB#zrr6>fT2P%$-p`eNZ!+N@Nrx?0|E`p%I&TTw(X5uVi!JJDi^LoUMLwO-96MrR zty9fmLB5Phpe}a^9A&Qv+_aFTH6a;!&7j%AV-^YYfrz^l2&2!9G}hZX={@m+&wXO} zAM0-K5#?!3eV=2m{8gVtH`=lQ&kAsQBI(X4@J9RBkLc@TTIZHY($|t-@wW9Bj(%3h zIboVrxecy4Lc$eTE?0aPy_rctDL9j&`NAG&zlDdKTVQJEleQf1+lJ9v}VAA?2(b)un}g9_i&dCi-ulN=n}OMQNM`h5gK zbZBYry#M`Sq|;B_<%1g#JIf>oGps@ z_;jJqsN+yy7!88j9hyxv6X(4&=XK94)wRyvv)WZ1lcL)%9;ocH_}mWK%}ghFoRB;) zdd#FL3-z82RrqiED1VEF9D4VzXNs_(N?WwH+(+<8G5UV}oeXwp*~Wy2Kd-FW;F8Hy zrPNOfd)UyTCis4-iZyvG->3gYNG9Eca)_+r4EfZY})ivUN5KQLQc>0N(fyxf~cP z$U%qH6|6t~sQLN((La69aCchsVZyr&pHK_g$!Zs|7rY!z>L7v&Yf2Y*a#L3y2v;kL zo;eWHVV+-^k2?8s{xt&b8^(2vVJsx;YD`%cIgJp3AVmcwD1}weDwKr{9~s97*+P35 z{+{=7s~#`<2Hy_f{C6cT(8e$3Irna+pvDfdllr$qRdFkihepS>;oQbESrfrnjnnk( z#(~HiHR6QNZ3q}i<=3|Zt!Q<8ioE^&PkyqvIT1BGX-d;G!9Sid+UUPwE;yE9`VQN5 z0*`nQ!3`moCW;O#zES!E5%ukkd zyx}s!Zc4OOinqiAR)6)QI`_xTzh>gQ^_^Q%`6Quz4LL=pF&}@2DL%6)dI$#LD^(1oDi@dOjyycs9XRVB1A-kE;L?(}EQR?@|TW@DFfU(fxu zaEtF;{^hB4;4;>lIx)}Bp$twtil0)2>TC-OQXFo*I20a-<$K>P$PX+ux1a@WgmD+|e)5_C59+@yz>rL6Bj`#i_7oI;;7M+))#d*d zLk#r@cj{(y`$eyw*#Y(1*3m)HS-)~E) zNjw_}c!7;Dl3~F%E4e$dX=cbGxQq^yRgON`sIW6q?ZQ2n&cayPVu*SWSy2<78?Xm) zUV9zqrx_@V5?7%s4L<+m&OT@^IJodZ2tS z%HroaBa)WWlV#-PL?!XIxu$?+*BxR>`%%<=s8eNOD;^(cHHZM184p2k(udX?(<3Vwmv>N*I#dtZi$^+H=*oEht0Z#eyqg@^+5jyYUNH_ z@q`7FXJDO3A9>mQpiwiOgJVCLT~PsNX?yC*il?20Q^-41e>x@B&qt(YFKKKhWVA#vQ`6pFBES%Mm0akMp^- zk3@w6qBg$C6-#C$7NEZdaqw?&E|5ipmlYF{sOBowGl@40}vHHO3C zchQH^v<_^{$TM>RvcQ_xKLByhwjOqlP|Y0*y4d`d zafDgKOq8oH0Z5=eW0w(JX+djr?1SJgq@Sbys2(6G$byI`UCqzC^z*NS`{f=qU0;n# zgTn3`7rIMFg4%=N1!aBnmNjJqH}AK8=wP8F;V6Kz6Qnzg#9?DoQ8V2pB;amR&zm~U z^IIbhrq78VN;XA6EwSGA=+xZ8n@&$0g}DHpzu&&XUH1e5I>wWKcI;DLtY#l~a-lRh zE6Ve#4j@0iDlT%lrfwjjS(Q^uURTERCtAD~6(@yRHL0oWr{$~lrm*L`j_v*yg*HPD zA|oLY`jMP%1AXnn`uTq|b=J?NN!SP=q@;}dR)yNMI{bGO~u<3tunL>+)JuKM%wwQ<> z|NpfX8Fc$ShqslWMWNy=QD;wDZ%7E3omKdjB0=cX3LtB{B_kwM9Yp<XP$meGZ&K zutG~wC0JQ-M3z7OL?*yN2(lL1Q^9P#sj9}J#%hIsCELQmh?uj#qWi8uRkeObUB#p8 z=pZ@&{n1ZXj5WOt6|p8eVtt$$KZe>Sp4C-i+?G6Ql@4CGKEx(WLb?0k`1EIOcN>ampPGyYQVYkrTpMJ%0mej znNH}?P-FWpZiMM?uKBCyy?+XeoiAJgt-+IXvST?%)T3u`e^z+0h70r@;1bezBgo{c z>D{%W4Tz?Z%BzE+JCu|*o}Ih+D3ga8Pn%hjYm?twB>MO4$f&5`|Ct3l>AYRi=mouy zhg~Io%pH3>fm(}mD#6srNFS+MDyWY#reIy7hT<38lcQOkC<9-9!kqA7;v6raV zAUUqyYoaQkbniuFT(i}v%L>3{`Vt!)X46q=NaRVvsBO@Ii7+uv(e}9-bY_R8pu1q9 zFv(K+DW|p}d5~*vORO*#;jttIW+cp5%d^s63~JBbIg0zv`z!RoATT|2rT?d%Lit_5 z$`Cw=(M!Wi@O}@ZG1fVw(=rz3mg4q4s$kr8XvEh z`_5Phkq``Y6gh?q;B0 z@)z!VOI#uty{@%qa&7M)E|UE%LT@bfGBxXp(b**=kLP_Qz~y>heW;0Y_|wp>Q;%1f z`+^heb|Z95xT#=!E<$R*UuE}a%RAO$upk80KTnOqB4*OzMqSNGrQ6CG>hf&9yUL*) zhiRJh8s?M3RXD1(@VBa^$6|D%GgoK8pS(Z!n$welq@IYvZTB-j%uiKM6bijI@|4J|Nk^Wl911-fGASOHqQYiC^3Q>bdKm#oWJ5^`* zP4S9kREzZ2Ew2aTxl}CUxB)9CsdWEKrKGy+K^PTqd%o4VWVbods*2RPP_EjZo2aA^ zVzCT#OdQ-opI^_3zFMJ-0@Ml@`ptPeR+Qbe@mQV6%UxlisNHqPB4%l2xpokMuZ z$_28rO>VTZpr2~;)j!_=yuz3G{bsD+HEY3e{bb)*fQuU-V!*m`(EH=oCmECb+JAA_ zHMO_nG~BZdOH7{E0ti5%gn7+;L`3PAeEN z32M}*??NT)b(V=+NR)HqN|W);jgg2YwS>Xwa}Jl5mlUbR=xTC~9@`1U|LNe|s~9(^ z293|hPxA1=?qjBha|n=Ed1{+po!#$F)?fA!-P$D%tP-NrYGhAPEk~<5KGZlij0^YI zI)wiF1_ZDBxHLH>=m#3jQur-V`I<|d|^bj zO!yf??O(#k#cwxFhEW{-c~;>`O)i#L-WFhL^A9oonauq2Ghw>JG7TS3x^s~&jJVDHvX@Ax3i_5Pdr?O4L7bADK_sdH{7G!qP1}kff`tbP%e zXIk|a_{Vn#xHm?rUXX8fyYZ~E*wU9h?n?L3u`pu`U;0BU=NBxB_B&_)aS{Vi=% zbqoldhA8qf8EH`z@zH&GO|Ds;9G(mB4LuEr?q04u_6`?!ZeqXC`$9Coo%?<+85MoF z7>_lk6enve+%?^XeToJ>4rftY6pWpCd(-Brn2e8!dM;RxVK~N@ApgvJB?uFIM6)C0 z;PdvUWmnO=md>v~&|!qF@x!QX>SmGXdLk z9{^PX8!?no#LmJz8rR@SW{w|0%rVf=N`JwxRN=~?4gN8fF)swbxU`r=1F=swjlu0^ z6g-u^vdaha690Y89qs+)kF1VN!6LvS3CDP+!)`k(Besin{3p1AFZwXo{j22Bq#>48 z=GwBmp(8Q~F$+rn{gZ5oqVH+U-yT*w(B~cU1Y4{Al9aeD{h{cx_F;Ku#=L!pX8zz) z7EO)hpu3iPLlWKpl zBNY3=y!?KK%GJsYQ1l~~j>iy0+S~y&rR@|#SO3rrI0>iWGU)B#TWguYivgsKez6Vj zW1uD0mp0rkyb9=z>*6ZXElw1{hW`2JB&zICkMTKUevW*)>BIrB52CeAHk8(EIrsY8 zO;lK}xMi(E-EMe7H>iF84&c1m6Smte5BhBkq`Y_!b^!-@?V{kym3e!&O{?ko+c3Ss z`OzI0CQ?P#!C@3@KqH>K!|j)$E5;Br&8u3VP_JKtP`x`+U2-521w16Iz(s+}>|oXW za5K|FqkOA&u^+f17W(_eJBqb=wae}cD&RYz41 z(TwK)^W@vnl+)Y931z|cj!9?Hhl48x3vD50{7wqYlJXY+i9BFGp(z|Br{YTU(4Jpi zzUljUmbH(Caa6eSbLHe)CrY08LkhduKrvao)>CzyQOE(4hSgv6<64z9K^6qg6zp~V zS9I7%$;&nP;zW*Kd$4!|1J1_~Bp@op9~)opOHH2nz?)!Kh(srbc>Vd%x@da8j0@7| zz#-$SMz!SX-;$!8lH;X{V&vr0fYy;1_Z##~(@Ebi85spFM@A?&kzK#Be0)&2)m9?U zt+nuB;YigAL^ue22g(g8VLsMXC++Hj=yAFBg{VtF{`&EY>&*^aAoq8)(S+bf!6z&X zn&_}Op!mg%owQe#+B|er0jfUeHN9cTRa2nOuiv){=~{4q!=}JggWzB}>2n!G4e!K2 z0797x`U@*j&bHIz?wy~MXhgDtbsu*J5c`4!W0Z$;zxiV>SU_$2xi7OxJaCzR4#(F6V2vx~V!WR>XpiL%Oray^Jxj-4FD`iZZP(!f^dQ-z>++)Lh; zmz`K{&DVB44RPO#CGldYMv;V2kALbUT;s$^-`~UG^ZOJri739UZ^r&&xWRa zxAeK67Fg+v^DEL@KfB5P>)9FlrS#m1LqSYJq+ny}eJ|*ccSpp3Q+dX%wJu*WN6bd- z3){?SF|>D0{t&l#kNSKN(Yz64mAD$Oefd}8DXjYZBm`jjcOG@r+9ce{pcuozuMcBy zuQ8+`GO`A+L52DdoSPyTw~RV($5o%^_%!>zS{#d&;D{78$# zPY@DQ!J)8qb&nY?H9p|{#LZL`cSGFalYOLa{Iix>J>#i6DxE+x4uXAmn-<#@o9+RB zZOS-UAGfg69%zV@Vj&TU$VGO10T7A9?MQfLKkxEF@A5n&N`@ROI;;vHd^a#CL|W(^ z4y^xY_BgR+1EzgJ_)hG`-zUB4fv<@eReNnH&~+bnX8-u_{0TYlG4iibjl-=Fu^Fw> z6OWRPcmgYm((b_y)BTX)vs0V_JXdEB|5XZ-PgJ!}ZrkTY9`xJc%U-O4Xas>*+m5Dg z<;nTG3_asR1~>SDof;T@;>-ypG_T9*@)q^B7F1n1$+{;Hyp7i>;=~+le2WPMMgtLU zs}CN~eF7DEgq)ox%V{@F>cc}B8E z2`&1^@8|#?}(aq#QR;W zm#yt;^Mbx6M()JPJ=K@34PF&BwVZi={+r<(jt=v7YOv=i@fE|`>(=k6q~Img`s**E2f6y>q@=(od~tuSCt`fffHV8) ze98?LGg!vO8h4cYao;$wj+8XJ#Tqp=^v z@QWA16q?Om1z=_fc-VQ(Vaubc{LilUK%djCsBg;0NPt@%A-$Z0p(m5d7r>_gJ|!LD z|3{#OI6f}+#4*ck_#Wn7-av5ceB*%C-U$~bSUog7nXJ;FZ`o6!)7kMu&tl+^4VsHd z%Kv(JsEm;&{w}(nXDco%Jz|fLgOk7R3zK8q?MN&7(O0wGtJU9qtAD8gdsuK{r$Yy$ zzm(6{u}u${xjgQQ`Um33sAzESvqQTZ0({d+&e8;jO7|j=sF}ip|P}TpoDi z#q)USMN45pYhr}fCsVw?egP7ADe=1kbcc^jpF1|br`od{*&V))UTv5SG4oI%U;SJU zS9X@}!ZfZoLNB!ynSRRw7sS&kDo$~#4J1*@nexu0v>TeVOD>;x_l{3k8mX9P+GUNQ z)qHnFnm1MEy5P{rELIa|0WS0KL($RobuqMSgbCFp6EcX#9V6Jb+3^orcm#^yY=I;W zC7w~OSJz|J8i}nFl5^oR-iI&E1o@fv(Z{4HE>kFQe zg31`VkAaH;IbjAP^1TfNgGRqRxlnP((Vkobj1-9L3Nu`ZVexTLgW5CD2*OzKEWpdR za0^6M62%+QUw64Y>>E>3P`j}}l++K3aDt6J_dLsHueolu_ux`@%R*vIhZ~1QBBk)_ zi=GKpJHDeRpVAS%*AeqG6BJLMMaX~^SP}AT&`8LOYM2eqlGW;@5NRUU_(C!&@*T#mpOx znSDh7NN;}#ezF(3ji2b|`Gu4%Lxqoz45|#cMo<<#Gb5G#vJwP&I}ybaR*OliIo zwf=;Fe)h?Z4sNvl0X@4K5MM_lo=6y8}GzMTqQ4L1EynIoW}E3WU+(QgQX zhq1cyt%G7%GfwdYemdgIACVX0AOGXkGTG*iT1U*KvXJd~QM1KO&%fnxCQWJS#;}$o zukIZJZ23Sm z*}XQ!JVK;Ioy26j{guSDf>Yp21x&i+WBjtuVD(pok z+Y?|NL3(OG4m^5Z+6>XKTtRhU`6WvKVve1ajrMtjSNV9!Ku}TAE@ZH#P5{*p;jA zM$Tx%PVvtC)bfM1|*AhvHMP{ z-PnX7{^o2$`x*~e5Ym`m{-s;@b-w&WIBmgD(S1jr@*nb_@55+Byisul0bOHy=VQ6Z z>n)j6X6HhktE8LCKfC!HtgE6#9F1^qC|HZbpNDKAiV4#yDkz%I46$yBEo*Y@7+RTFqJ%jr1+E^se%ka zMV`J>M@)Y5t*_>nV|}w1+du^QAgjE_q3!nZl^;%e4eNL&L2Y5?uABwsSs+FeGFY3F z7W44M4Im?i46<{%2X0dTW)aFeUXNz~(Kr0Vg?c&*2|JG8T8&7Io3leB%T zos78YR?m`BlVK0`-IiIM8q_k^9eG@2ixLMGD+82uX^wNOx?;TQGQ3#17%T*_`9n^o zG*5@l_M*c6xB(jBUwt~kRoMLKx*5SU;^W;pdw??)cPsFXcV^#l!Nv~R9I}{wG-`w~ zn0Ml}VR5a$g2q|%+;?D?ChmRW#R*qKucdj~LF`tB zx4RJS8>6X`!WZkow?HyNfgg-Hfr?j03yC>tvEoXXUjUK~oIvAq9}H(2Lg&9~4Go-* z*YP|xJNo@5-&p-l71AdCr&zeSQJCZC_itHB79rB{>1*pdf!pg6_QLjUxFXpPo2+snMEp-Euwuf zN%EthfD_K3qI8Pw6FmUo^J2ewa3$Z=(lUxq&>rCVgTKDTot5;zl=PjH`v`o*WuR97Br|eG(e4M~T%_n0(rCoNI zZ@_jqimd24KwbLAe(QGJ{K(FJQdF8ju(o$ZFb8h2ro^&Ynr~jPk2-s3dpR5^fUF?E z^1XMo4z(6BQ|#H*^-^qoR%iB(Yf6gfxRA!Pnm|MxuK&N{5GSZjyZY&u6p<*j3Ifh; z_Z!m}_to!ufdDsPu9_yUgMDp?bh|oGcO=dDN<>!Mo@v8(>;M%a$^nOiiPQ;uZxl$2 zzFQL0?JDcvwuhB|;z27WvFJrpHyu2?-&bYCu2-!O*L4f=GkA1+QB-$^i31D~Yt#RT zu2}B>gjJnqC)_tgY$z9UFMsULB%Ag;a~kb@F0zl|S8O`0H;_;DdQ1I$5>+a zr$A+Hyt!h_ohQzP2l(~XVlxj;ozIOw;3R)FyNTzjkU3={haYbiI~E?~`x(&w51l1mCwU$+}XpxW)onttt5wq*z#EDc(CU%uN(A~ zL}X4RwQ3}KQP1t2%A_Fojz=7%BP<~#u|?(m`*9PuP;j>R6&*${MqU!j1=VMa* z)2K(m7wO-3CS#`*JWphWpVp1+AJYtuD@{d94`9=y|K6d;S;JAfAXm_o2hmB+=V6DB zn~bYM za}N{VF4fPi#uw=GJot{*?6DuGIpC95B-o+z{%lCXRKyCD&=qtZpJn>)??=*pielrH4iW2( zVNA5$G|~u~d9|@<|E5K4Axf0^rmrICSH_@^FfF8!^0Y?EQnDz1A_xg z^GK&@G<+qoMUsQK(r;ELoo3s@pIK2e@aD}yEr@n6Z~jzpk^o)Y_SKQNyzaByENwtD zR*6xgdRH9Lkg1`FB0ekSgb*ZDPDO2X8wWT_Pcw_I-h_3LoTOj}QPTq4OE~)A1^kZl z$G5?vW}r=#)ub9Dj5%H7pMxBT&RU9nQ~(0Y%mB!@rwq%Z`jyET1DGG=pV4HU%#h>M z;F9bObg&cUScZ*rMU}249)!#+g!diNn55u+q_UJ;8i23-urkD=euD^1JsCXS;_+oO zh7>7Zty{>O_0WP~9=%5X^y-t9{T?{d-eX9FBI3XrbHj8-v<*Wg(fStPCcBUi}z?hhd;2y>#Q7&&uIhmq}aJe zf$mS#zF@I_)}kD=!_KlD9k=8&7b%cB2U(hqC-9Hs^Yjq|camO=Y@O-~$>}kX2RZcT zbkIMAuohgwaKb$qq*o8)jG=4m*Viz9+8H6Ppuom^5;B=RtrCSa3V*1c^hG5K{^sW# zP6Q*OOGrw2#=1BGcF5(M=^&H2ljNxDtGRiZcoyIWE|w@lY1tTkZaPN(!eeQO-BV3~ z7FD$%PNpDT$#U|<8S;C`D{o8_F^C7%MLmw+lbiOj7=pYU4>V22xPKNco6<81-F3A#@3>VUU7@V z<#)k@d!)MDAHUFC5eo&6oyMw|7|zp8b-5bH#yze4!*^#9aH--YCp=2tdnj}*V1U_eOKxN)5D01Q##k%^u=!naD!dt8xu}bxxOQGi zegoBGdg@C9XJWM5SuELYc4URg zOUtZ)#OSbvEl^1zE3cFD{k@jb{fJ<#PeYj?l%PiAltWKG|Hsz4wo<=$#N>%@Op4$O z&4Gu7M8^#`vR|&;g>~q8iL{jdC0cIo$U!F8j|aLT;*Im}QGzk{_fncB_2$sG)P}yV z$3O`=E;jw$k?4V9Zx?0T{%8th7Jcr$?;#UU!;bvMO!&2{Zrf)7N>VCv#L0~&Bsx3v zl%q}k)xdQ-zt~!WmN+S&VtoJ?R^^D4zGoYi`zp_@+doQhpO`1fx(r(aJGptUZ2dNr zm!aJUBuFda?6Sv;?N+(|7dl6ET*}>*0_f>{^(iE2*f3lF$AE_v-B)pXO1~RY5cyMB z>;8a6cesVS=jX*>^2)0Rt3Gx=Y|8bG2082JezSv0%-yqHol`>d?vom-{`Ul$jWZ_B`}(Lw%5M`~T4OjzO9P z?Y8zzPixw?ZQHhOPusR_+cu{4v~AnAJ>5_9^t&TY#NOZjPUMfO9~GGqbyr1JR<3I; zR~MqV#gTk1x^6a39^{1x;OCXV-gVdM#dP21QR}XQ?daru44oEHtzPp_srz=^E+4t5 zpVuR%$JnM)Os3P1$%60eyB{ykUhF8*jgClq3!&P##RhPj-VOC~O^h033sjk^O0^a< za0716)R(3VGEs}_r83HRz1Kd{4esxa5jXrjc(7NoEHSx# zI@xYW`rZq&ryVXo@ia&=IM5>8-XX5FyB4OnxqRcldUOyl=3oC!_!&X~RhZAxD&$CV zQ={o+-mP0WUWED}vR<_1Z`K^{PN3*T1qA$!w;3rCR#BR;LT6778|P*g=0}imEM zunz8iU71TmD3yO8ZN zXZJ`Y+=C`!ndIw^R^rH)Wiz-r+NT6v4fvcbJWGm|-4&p15^o&w7avre>J`<4IJ8cC zHq%YuZ^=ui3Rzw+(?92*dCQ25oRN_H85^j`pXQ1mdZDiD&(vt+dW1v)*QrAFI_Lfz zTH5FeB~Iq}%a#5pxL0GBJHMMbu8}&db`j=GlZC+ zMQs06tW$Ms+T2Kl@eO5ehMT(lXD%qg6j*8azBaYIaR>}I!o4z&vU*U^35bvLQ0M&; z;B{PlM%g_fQ)H?sG_X6E)2qj+mcql5KA7nle6oDL|5Brj%tvAOvJtv3fu+x*{4kI> z8Ps+!kiclBSzaZSt$_wk-&Zi1D}eoA&xIXle}Y=a6@e0o;PklE+& zb+#vlFYcni%8Cl4CL5!_#@ufeBow~3S1G@MdfRDfk}RZCBS~{fr$zbvrHKx^EVmVs z51SELULW_lVYZ&6a7Ho4`J6Mz#v3~NgIEWp>ML4QQwxUsM6Xo;wSOy(^b^rsNi<+J zOlJ5;x9E9|hC0SbfLG8|ZfO2#!^;?UYtg~kNPS~@gog`+6G1LvWV7tm0E^2nG_;kQ zX#lnffhcs4I=wnA(1ihn?$d@L?r?pgt!x%*%G9M4;g2Z-DG*Kn7|OZcYm*u9rA7OJ zRJS2+*c9j0D0|6h6nB(KuQRwAp$f?Jc(7vQqiC>e`*+}bEm*eIAwOglX$ZR;h5ObJ z2uktK!@T07<8e=E{`B0B4KSE~2@WBT-c zk^_6+GKe(1Nxp{K2wn`Bf&Edcn@yBl$K!-2XE5YQAvwyx07qO0v<4x2#nV#PnWrU8 zJzXF|h~#-2<-W=^OLeJ`BN=f7<4uxR)ZG#zRDV|xIvmrbkU~Mwlfnoo7eiA+#1HfR z8y4E6Idqsd@*0{qa>p6Z7)OB5L;E977wY<|a#nGU`vT$e$+W@2Dkl8(W60w=^{1Rt zROE4;qK?y^vnDhW8)OVsfiA*;#O1gt2>#06mk?&=Nb~S#7=*vm-pq+_}qU@Be>?v z9X|9PZV^jv<}d<4qju+ZKYVC60~MfrXIIiS2S}<6W&rkxJH*$Skee0fGA|Hvo5HwW78tBviiR0LNNm6KdwQFEy5GKeWRyi< z-)=O14E2BaMP~!L_-S}+)`Ge7Gr%+Wi|xR%skI=hv>{E*J6jrCyv>aXgbuWpt8b0f z{=X($f$s_Te>VdP$ZVF-0|mO|i~l?W|Nl(~7IHN3Vd*ych;jV?aY;5S$O%bhix6U{ ze?7})`@N!wPYXy#T#JEt2u|T^b>8?N&w|Xk@iN|9h{;P|Y+TlmZ(?R^1usGekpoRESR%U~9_?%EUD-!JsOgKi_CcMrYE&x~iWN8~{u-KXvDHi6jLQPh72WO~=f zMIej0nBz=;|+HH&_p%H>$peB*JFjSI1Y;y|N!Y z!1wn@3OvbZefKpffiSN2p!RLGq?O7Ddx$jh0*}`G{FX+05ZcRun)xT?L{$AEHb&T= z0lm+hfDU$A)7B3K%H#R*ied8&v>4aS>Wl6{p+bQ2pur;q^F2^lUHF5=o%^94eR&!5-rv7y+TEE7Un31UEPK^i;r`@S z{Kbli5fc+R6E+)@yF7;%)6_r^azZz>&8G)(J~7wq+%>a^cSjL0mE9)X*v;6(~M?QAsvb&Cd`IH`IbrO%8NJK`D~T^M;!)-SQ?4h(jh^ z`-u0wWJveiITb!)`t3fs6lXU^S04|U7|&l^^3RiUYp=jp!OM5cmk<#G5~kp@B9Q#O zb|2P^(9p6YLONo2WTPC6XGS|ubxJ;MeSbA8`okZ)CsF^V-8$5#UtK+%!cX2f^F-ge z2{&a~H&G#q)_?nleh!9P+4X2FSR7$PQp&`N2#f3cIH z?|u;fp+F0Ku&6~3gU$@LVx+1@W3^f0@Gjm`)~*SX!VWIaXNk`9!dBW>Nyl;q-NL^T zO`_rOvd3EHreY^zW;|-~s;4N&-7)k>kE?~hE9{MX~bz?PRySoZ3#t`wX zL>CC9z4Hxv%#*RVxvBGj@Ybh8)gRy87*3(`FGF((=+h=sDuyc_8$S#FiiFqg^_pn? z52yiPLL~TA{w+kJzL65khFfhoV2EdEDyVGMDwfUq@idLDsHhZ~vrV2;v4F^GLAdQn z0C%yh`b(@*o*b@5w{7_h5dn=u7F&If{RZtogEt>~bTH@ZfyP#MJ;Ev$w_jdw%jFfE z?zB#&c!RqBu7te)E^zyK9*|*g4B#t4%~Aqu58x$qm8A`@}O9KW+H3qo0SUN7HYKi}$8ChW|u6UKfJ= zQc^?#C3KubdEa|AeNX*FKPonMkUFN29MyG4p2y4m)xO%$lz;f(!U1sj#aDixeGGUv zw41sU&mNtaR%SnK-EBta7c{g$KJR2l6(2Br-#LQk_PEnI>B3FZfTeZT)ggT9Szt%s zBPKIED&iddx}v%?K7nuL91-;!eN1S0>1#z!`07x7X<7^}#iPexbk_&y5Q+k8kDihkuoFZR{hk>=)-vSd#)<_)?rxxBK+bH8D0q+a1Wl01 zQ$mwACWL^&(}*6L@egP6iY+?VF9cF%{QIFceJNJ`SGNBJnpC>YTR3REB z|2(~^Ib+5?ZiN{oMZR}w9m;8IT5k=jPd0YrR@3YE{@dmbx9kdc$xRh;~*Ve-Q}*Mpc?^brM{;+J%u+z z61?hP8W;JP&fRQ1d@TRZVBnQF@v8~I#^Oe(G%Pp3>z?y<-B+C8ke-A{;43t7yi*AH z`;*>hdH)f4T8t%A;r1l0#KRg@N?(`deIDKLNZv`|VTQk;sU8LU0_Ty>ca1(iB_#x# zx%k+>Wy{>I`hJ$J#}&9A`G#(YBIR8s_;M6!L<7WGf}rQc??tvpWx2gZyL7iJ%K|T4 z5KnBmA+qU#Jpy5rKZqyH!8~nvV{K@G%67lrd;B8}Ge_wCMP_iOWD?&7XW|RoR-U{- zHs5g1wi*uj36T1cJMpFS;3&ghNDR`z?+Eq$JO4f@&X8etGub(Js!gLAh>WvZzuh&R zH>=LlJF67js@6$mc*Jp{D9sW6f-%NeP*!|(%gLX3diJI~u!nsKzw`NKZecgHA)O=Q zm)J%uM?d(0bYYcmZ`hgvW+<(Z(u}psb%Xq1@7e31WRSoDuhYH9=G4IgAB=CAg(8h+)8Ir+&A(<;JTdQ zFxqCIY9e>!#JDH!@sU8LYkZE6e}KKHwG~Gn*S2@Dn&7mbIKEP$0827mx@Uhd9`D8O zX?@$si*?sHX2BOUmP0D4+6Lmo;w)Yk3LrGJ+hjv$laAC15Ww46VU$ zJCKUxdq>OeQ0sU3Z0Pd6koA9hnLCrv?*!pL+CQ%@Ve=6PElBWWy^Qq{ZGR7ZIgiE@af9g8@!{i{SJH@m-k=0 z2Spr@hpi{qqZ&nwh{59I+UTf6uLjOYS{AgT)>eR6(a19sNiPK7Vr_d==%?f7V^27X zaFvoh;w|KK1M=}ePX{XO(nW(Wzn=tV6d)Z&hj~Y!)C+wJ+^Du#Ovf{-cH038XR$dv;|jCRPzMJVHT;nq*RX zY#$P6s( z3N2(Kl{jLc)&3(X1NOgyw&_sED7C_xP0j_wf0Wi;|gqxP-)F2PQ+nlf6ALa9OC4 zK35IzRPc2Dc(F2jgme|@p`yD{l*|k!lO4=k@r7Nqa|WB-Qm#Z@yb##1f)ElL5f)s! zS$-Y@z)?%I1}@ButkW^~LP4s(A_p&NQm4fhnZdK9`HSYjB$`}wovCS>Q8oNl3vy&J zCw48*Oegb}N#{}lIweoU2l3&En9}w^im=cjnY>vP3bXKb;HbtCeX1C42E0%(HT9N- z`K4cW$Ked+mSc}k&%y^MVd01w7>KJAyQCkd#T)gJrA=er;LJ#Gh?^7LwQi5BhL05H zL4~|cvW=Wzm}rJXIf>sfEv~Hl(YUK4qQaZ}oIGd^$YqA}EmRRd>%-f;LW%4X?M)O? zZsQeRg5$)3$q2Vk5-=UH&e&p%e02LbSd_^T~=GY*OK?#e8ztk}lbg|D)PcGUzX^^|(R5#=~m%-RLW(Tehr5jnJ~h(tys zLgLd=2TwbozCkrc^DHD>A~L>8na=!y;SEJq-0G-Z~ zP!Az$G@RUq(Rx9<*o?9Jt&K}~-%$v!vJ4wV z3@1lmz7#hEHVNj*nO)}1F^@Q{-G~6yFYY+ue}jn2iRAO5AwSIDD(aF}o5#@?aaZO^SR+-J6}=m#B)xD`#B3kOV%nMGp;XxUkK)E{!|0vN z(S#0?7`>#J0zVEAQICU;5nQ8r;&kZHK|=xEIiWM*g)*8xw+!p0GNShBaESj=y$UL3 zVDMWpF&QUAQfLLWZaZ7Fj;e6O<%K>u_lqAF-c+%kuHWIQJ)p=iUX1{(1YvC3e9`{u z?L@Te(Z2U5F}QBqjN15N_UN=C15p;2I@g+x9&WcBG)=m#U)aISpl^7RWyhBKW;e$q zV&{pwUEp(dJ}OAWbM1NAySJC6aBOb-vKKXi@5+^ZbY4;_5tDL*%N3|mN+9edg3t>6f*SA(=KvjSM-{2-xcmtV5Fx8swL<=VX^D4eGIWouryS) z++8qu-`Jv`XvK5}#NHjB(Vn!v%3L`;Y!=|8Xp8~$h{CQ9U7B);~v>5@VgOPGdir$?Z@(Lqg zP`E~FDR8hz9A-pPKka~^u&jn6!r&&LbZo zY1+cY^0gI~e@|eST$_Qsw9$^%;{%nP$no?23y;K4<~PknAERZ7KXltC@GabA`^yKD zq{E=*1y%uPJTW}}x#!02UaXkx+h2oavfn=KkcV{L*loD<2Lp9*`*|Bw#fEZkbNY<@ zWXO$X7k6YSOmw(WN=3rE;${Iv72?JC|m?bb9+$Qy71#Md7_u>IOJwVc0RC+ zi%Z)rv|qB?BEP~b!dcLS)SIw-JbY+xdQjN6b7Mpo$c>c-H&8S#F(P+iO0fEf%M2^S z6LI&TLx$l62Wn=7Y9mJMtb#jF#jBMs(_l8;j&NAnIvidS(cv9!N8l5$gE0vEgj#*>3dzYF z0uXb9?{z_0YXY&jluC(YWQS?9FHpS@SoX0%|J{UqjCxw&Bk)S(xS$VDP4q=>kQr^Y z5IJXf{FRHbei_un__O2ReqO0O?`k%e2ID@w(9Zia9oLN+1g7Kkz#Fn^1uCY%4e=r$ zjkuIX#8QfA*b(pjrpL7~0!m5Oo~2aO-lvNVyC&5Z=Q|c76Jk9aCAfs#i0Y)zZd-q1 zAy%fGsnl@XsWBeA3oSscNF;3AEpbQR2GZVEGt2&VfNZ39;8d8K1ac8lCQ^74fEZ5W z0}YlvBTF`OZqwRYRIBjLiG_?pljaou0~0OhUDh_c};dl z2b%lzv%La`j9X3psa-p^N32Kl%?G;e&0i#2ncUrIF$~b z7tZ13qy-CpIzAy-BLs0c*Y_G$Fg*G$gv*0UN%?@`D-$F46oQCBA;v%7$;+y(`5~&e zex)_(7V|R(eDVFlxap5h7=Ym3r~r=d;QinGVolY}>jyKS)&uq&9=HE_CZH~i;qB$# zfS8ZkL2ghNXg=BrJ~C=DRHmq|#s@1XNQsf88a5?wEn1a3qC(@tgSh%{Pi)eg2GMX` zW>Up^2#wBsz!b#zz&+A*2xrLC`uK@Fm$qeK)(6MV*ZoJ7-L#-m1>#sF+gO^BkSh(* ztChX`2ivNSxO<_KkUMTx*qxvk#!?$<$LjSOdVyf}0fXe4x<75+wIjQ#!zD-io7?_B zGcu#UuF!Cftn8~4eC)LYWgD{QOB#FF>JtOq^7R!Oai+RRw(3-f$XOsYE$LS&MHo#(C%+D`^@>KfvoKzK*;G3!7oJRD5Sf(73 zHHr`>J$MMIQN;PZAw)Y{rt!e}pPEOpzcaM!t_6n(;f)}AHe=TBJ=txnB&t$sx0|iM zWogzU5H~j|lZ_}#vJ6e+3k;h(s>Tv^A8O20%RI54Xd4Qz19Eo{1$j_dlh;bQ{GZrwj_yy$?sj!Q6Qxs!W5+|mAERN5_Z8A1s5S$F zVV+7>J3fEEH>O{tXx!4Esj#sY_&LISP`H?@zc~6h&bBzrW-4lG1lndjXBvu)t!U+e z!+tB9Hf&EfsOnv*S9%7?G*CJWS(f&u9Czuon8+8n#LeRXcei%!gPj@j;l%~xnJ%N?Bkl4z85Qi`7iQ9Sf>1NHp89c_!XNie2~)vNWxP&p<)JChD9n24}ZH0b_cCAZB!}f>cj3B7v0I? z*_NxA4Mb=E7-<6*hM@h(R7oc{IS4UBdnhkQtRX#m*;lXf56dgb_}A7JvpG&0-7EPL z{qL3Py$T7C6w0-S*ibJ5d30n@0t~@U@^p|PhWqe>zlY~u$~k%4mYkcNKcSaQ3)RV0 zncN@C5*91TRXvD{&!=lj(;OtEPCo2JX?RGG(;o}#;SUizdY3!T`z?!#ZJcpiAD})zy-HFb|KJ;nbuW4_aH4)z1%Ezr@3l7^_`(a zya>6wGwN)D8~bju`S<_}{38#7ibqA7{2DjZ-`%=M0F9Au%sQS< z>_}hiSNC=5b@SCGWZx;u(LAIm4kl1lhc!rtygP%Hag@88k;YUe-3RhdGd7amZm8BehP-AlK!% zhB5_}1yZz*`ckBkw@yO!~TGfNs;&O9XfAy<%DF-NY!-MYGM z!-V$PKjevcuUVR|y7yu1$|Xb`X->E>=V$Gs{f=pM#9zX;W0y;y@=u708I(iH=msZLSjt?lMeo=ZcxqSs zIJOx;uD-eV_w0GRpDi$b+Y%F-ocZnk+q6OiY|%IqDU4xn&qIV|gU5ODbo~C@ii=1ysaNotj$a zDwUojmo_$F;V!9J>+TTd@Kcg3($s5SSY%pZ8#q#@*B>W-&1}2<&`{O2@^iDz;_hNM zEf+R3FrQaUpwcJ`6f+*-QA9?LNa^g%CsX`NH}@7RqQ{aQL}H|ZD$jRT;DTB3%H!_Z zGMNb;$-j`B*Zs-TgC*x*q{o z<^fR^bbfed7`0K0fg#Md_|2=q9E}t73})TbPE=NsF`8Ts5X8X&DP$j}X0kBYF^|bS ze)j=cfHcA^*?732xC z#@X76&9nx`b{xn?}{>jm=W@{rdHZ~cD)lD z1M^Y=6|(498dp_TwnM>Ivp89;rfsHJmq)((OJn{3W+QH}c!~&Vq>!OaXG36v-q$Zn z;-w5Nz80DKOIuNG16*JJC!%vD-deV{DV!X&OPZZ~yA0w5k0x>vTYkgvirT<>>VUEV zDwJiZ;jRHGoCR^d>EZclB#+5#Pn&9d4MK0R&7AMr-PYsEgWoaUdMyG}uJGHRx5t~p znI`EtwCPu|*Gw$jVG1RB!}$RX7nlw9Oj14p5ls>Oi3HV^K&-Qej8}36~E1 z>Fd(!-RRi5ik5|;1i^9v>?G1L5?`xroW=#LlGnAe=0atIxw~7&bNL zOq8<#FJp4P`@^m^O$rB~TDYgApOXHjjmDhqfhiI&{abP=2NBRG97d?5`kVQeBx+)f z*3e_(#G0@_c4Z42_`!axM?wnrPMD*^Q730Q$3Ey{3;3fc(DfhJ7CP;3p~haZK{>$+hhc;3GbkVek@j}~rrc#8G zeOmTslZmv+YpZ=}nPp?)lQ)m-x#{V>{0TltWor-R;MXP#sxU;Uf!wu2GESv%S4B=) zFNp~^`XUdUT1E5hY_uFr`A}?E_%#k`2qiDj|JQ&pV!4vQRKAYTPW{S?0wS!asul6N zYxM{@jGoFo4cekE3Rlb0ZCnPZr^@;%1<7adMmAXX3_8$X%@^62 zBeO0ACM4Op$n${!tr#cN3oq2RJM5ne1j4k1<$t{*ce*U9OFFdTnwyCnKh!m$UXu+} z4Yi-QrF%W60E(+I41cmE&&O4%YJIJT^UE{aKxL*UDT3QOj4Mz6coh{7L1stgcN0be zK?G}95)Brf*fJ?vi$?2v*99EsfU5sis*H4jxXY2)-;h!NM!#}G zpgjKyg6JR%<&1n4J-8+d_Ac3nEWAYk?rUWypv;VZRR$Qlx__7~+zQFRBCS$ifVU(- zJ&}23PU{tl*(`-N-JW5?aP^DD#YA0IrL*?qrr!d{y8!xZ=?muZBi{QpCb4UTgJVqF z1TCAGYoz#4VIl%)O`BHKi$a@Xe!&p91oy4}ZC^fI>^l3FDo5Yn>`c4=z~yoW?@^$@ zpwv$bK6@BuN}1%hH!y=+zNs^dlEac9hhAsTT9vLZ-sRU$wUZUmyG4tjHGUB1qelOADHf24@^LNHnP84`uuJVy0Miat&+6 zV>7lOA}coxuJH2pD4m7vcR`CKjwuOkgN;?=?^Y6UtrD+j6pIu_>|`vw&fta0Fh=U> z9->zoqCRZ{)v!J+E~F^*IA@pviwNM&jfK`Weq_9ZYDqcUssYW6_|n}~G&4z|<-#~i zIM+z8B1UyhUxFC3W$Ud{#^Zt+#)u>vl_VSRURm% zARY#doB~jKts9KZi|k9xi{Kw{N$MC3O^>B=lvL4mx_9QJ$ zz7&-eLkn`cZAu{<23d&@ckl_P4pK5lI*nV5tsEC>&w~=3-7D+9Kc-CQ1RiQ*2fz?G zaz4ZtAD$GJ7V0qlkR?JHY}-r0hU7VEh< zb%>VDifB^~H8f~K%HrRe4j-zmDFC02xq{h7i)lzIHGC~W{;=fG=NFru%>LZ_J(*rc zZ))NbHcw-O3W=4z^b3olDv}Ue&1Wsk#D)EvQh)9U4oSGdliTz}6Qk_4Cy6G;mNz|8>+-(q6pmz z1)hP)1f>SlafANlp7=<}D&o@tbGrUsyys&kSU{U&Hv01f_w`+FE*iuuCUFMtSs%}q z1UDchq7iv+LUjThmEzzdU(p9+U8L3lIx3gmnDmS`yOF5WIDYW_Hy7RRwcNHg0lYW3 z-ah4EvW5oEoXw#>GD zyxxzvo`9E`<^5BKTr}JUCW95S$@epuXes?*mn60O!8U{pFRJ>p5O13HB@4MLutPwW ze*a6BHDJVJ7FFY(mCd^qpWc>#ue-8<1Yi5>9)hF}NU6r#2vYDPJ)u(UkW9Dxm~j1$UU+uwJE0(zJ~A{Nwa|8Z)bJ7MFx{s8u$Ln_&oG^ zAE}ONV@gHEzCr0fNhB-&E@_TDw)mdJMe1czz{Qi-BSdvfX2r}dcq{$w=@`hcdrRx; zk>!)T!_9X1gPTsgi)$Ck=1WJj&rd#zyhGt2yk%VM28*#72H_DF>8UmMqIhzDy@eG^ z7NfTbE5wK18Vpu5!sRJu52~k9o3FOhwsV@U1G!H0TE+k=tOb#|;(N8tcvoVy9l4`b zR(R~Q8!6A zPDd0zy{jL6PXZ#xZxABd{mB&iz4a!8%-F;@2*+R9e=XNCPwGcELsO#L2=0^dD{KXR zFXX{ya$-hs?(9<>NL=1)X}_=^Bt2w1AhYOLn+IM34q|$Y!D2VBtSfOJ5xTkJqa12Q?i4cN$@BWokYj$6qV$;HDOQPNLPU z$Vwx-;}E!3vbqwWEY3N<;V?qk*U-IMsB_2m^ql+qqIxzR!O&y?$nafm@MjBEkJKKQ zr)f>T+FbZH>f6C)+uBq$IjG>g>(D#B^7>zy7C&bWm2dmSd^gGn;{b zXC(e4N@t}24>Bj5?7c5MtLfpzd`gM=8*+dVF+<$-F2ba-;>>{f#So}u25+A~h(4_R z;8I#s(cluyY0F05Uw7K(hoZJ%$~rScuLaqTnc7~-%dXTJ2yOhkvQH5fMK3}vloY4Xo_S?>z1DkoFuSh10D2+?{_L{OhghhU2vI`RraZES4 zLnCHbCMh5l64$HKm1p^~lTwBVl4Y2EEg^`=JAaw9h#lA{tn$~NDL*kiK~i90%~i4L zPx!w?EG)n*b$nZEJ*WGuI+mh4Z$3k&j%kdxN0ac=?5@#Xk4*(~YD7E;7rY(9uhcSW zPi%+C@l&~dsLxt$Ylc5z#9ZMJu78r1a-pMbxKQvnKzA%(6u2Se8=D}>y^)r*4N*5I z^s+wJhxTo~+oN)NPe3b@W8J6{#;`DlEOo=agde|S9n+$BCBDx-rx8+23^&=-c5_j+ zXu_29wIFgsxAoDo#dAHXnnS{Q*1#_m^c@&nmG_p_P2yTE5qmwen?L7KhYD$xsS}m; zN#uEl84(;;7w|!Mu-gep2E#dQI~7!b(yF4yvc1@8V>(IQH1F5U;&|iYv*oB++fgW=L92NwN zqTea!Wbhl$XFUj>{n6lQ=-_$KpnFj zucM)Ix=ZoF`M!}-F%>186w>pz8CsfJ!@Sb_zMXk06a&YKy${vg**4DM?D}i_(NJ36 zYy-Kt>3T*X0f-2U^5bxRL07C;vw6(P+B;9psFSNa-(vvxP&+7tyricdqeofm9iId^u8V5cZ%XoYhUxw)FU zvDqcUc3Zql?t%wDyYum_+fJeOE>KLM03(!gg_(c9pHkxe(UhlkD23}H z5U+)YSS zJJQ4`Cc|zEw&24w@3OKo{$1h!-m+nSa{HKKS3;*xUp^%1Qhm`8+nXXF0P!<2=~L_a z;YQ0uLIqhFQY)yb8+svu{0*UU0t3X3YW(0rhHyKQ8F2TSeR})8nh+c=E~*0_S(xl`5pa zQ}nsx&=&STl<-g>L}>5_7Kc}#NSX5zD#P<9Yq}WFK@BW_8!Z*gOlnQ`a_RpIC&44M zSA64mh9m?M{ok7We~tlBSU=SROQNtqJ#PQ|82|HJmym#ZT9=U6kN*E*P)+_FYYS~^OePv= z=J3^tQapT?uL3UMcIfi{zGUZ6os#5=4S&*05&K;^=hwol|Nv?imw{%?E}3i#Efc$ngM5Ym*blWLpZhbn6v`Y`t6D zdCs%iw`cZ7X&JLPBr#ggqP1_)G%zLlljg5y&u8`wepg0I;^P$a+TlE5S0Hn zQLxtf&AZMarZ2bumVe*R8?|H%^om9o{jFe;KW|R(Z>yw#N~L293K>|M4(-U9hX`PJ z(axioK6x;{yy%YFI?QPOz*1MM8Or0I5Ogi+EZSVb(64@y)w#2Zme@TO0ZO~?e-Jfg z%;b*Ny_}<}*eM#FTnJ+Peb?kkH@JReT%`d=>G}f2`)UOtlq6<+uMDdv6GL;&33LhY zt5ARu6Im4DdAVf5SlJ5e!LRId^N`c3&n&lB+^b(p__`i=IpZSWxa%)K7gnWX`n)j% z9N>Z}rSb(f1?&NI-3)nddv7%+Jx*mMhkYJ===iv238gPX7-wz83KU3)4BfG6b$#&B z266jN=G=m5wsbrS$`n8|C zqj9Ie7vFR#{dhP*a?P3|XCU!Jqp@eoKcVV)zJAA=suwnOn7Q7Y9#X$z1Q0gb_6~-$ z?#BL}j+A9(NVe`b&a`R8bZ6RL3NdSZ zcGNxr4X9@*Pc&kbNDI<^%T&-=3`}i_eKcTh4ur7k4H2Q|A#HHf*~H&nb=NYw;<$FY zmw7EzWWsNz1LdlL!ZOtJV?@z$!!jwwf+y(ISz} zf!W%dQOryW>DuP>Pb4SyTx6-%OpONdK?bSXKxE>IccFU8(~*M>_yJ0>q+qqkfbaXu z&QD$DnUQL?9fbyPqD9js7S}+|blYz>B46{$?3l)(OFI^P>=R231luiFD#QS zv!EIJ_@bAPilMjBYOGSb%88VJW*jX}->g4hC6i>HXDKxj(U?NvU@$U1#5Xskd8*v{ z_A>2^2pIt@#lQF)p{r-gYibw^pzQg3L6rYHwl`gY+44Vjw`fY=dFoH5tL`}_@<>vK$6z1V%{v=SvVr%)T8YDP8 zAi|5J@23#N!?j}dQZynF(0PVI&&-Fd?U4IeS0U7H=^HU+XVi!1+TIjGIG_`$QKtVrpac>`5DJ=;1-m{Nk$;$7O`cv#VqntLiRso3C_k$o;^#| zQbyDr&AlO!h?*h)MvJV!C}7Z5ugth9^@Rl9V&eKUH4%W?j6;t3J*vD~n&{7jh9h|s zFlhwc3d~8PIni2LVdd9ZxZcoJ2^;4_$0QG{4*RjP9618DwXvj1JXWdmJXHyj_ad^j z$ylt24T^r3xa%3&HbX!V6Y#(kfuU&NMgtg?mbQvac7%^{`;D;Erh0 zg_C$-K_If?!NkEL*_PVTgEw@-3nL(+RNem-+r`%IzKZiWzia%t#_8wu9L!T&yOz>e zZ~1?{0Fdw5xuS>hMM$55XjQJB-zVbuAL8y?Sc_+PR4JmZ&J4Egk*Enpm0^ z7N_4vl)ZK;Hg}oJr)kqn)RI_Qad^b5O4{;rXZ)R{tCSk>KY4_2QAT(c?Hk4aSf|vY zUUK-0wX#Ji?$Zm|-WhD__9H2i`h9VX2!qkUniuu-u-9Hky`9Vc2qEz(iU&h`mB;q* zJS$a?l|@7s_jDPvh4*nerPeYu(XVo(Ch>HEsj|W}v#b`8_9-FZ2GfuD4K1Q1gyZfX zOK^bzgHbBfUNXlhMR;&danK2p?VNul=icC6N<=3l^aDsB9YeHzg}ps}VpL5nsK@Fv z*s)pT#Nv1SMJo5RFC1SI6U9V4zYQ#fm96P{R7n>ig$qhpEO4?uOcXN5zz<7@B;%tp(C{u=f?;_|hM=sZ|x(2MlOPPyadji zYI`}bJ&`EBsU+r9?tsW%e6DxO96rKhS%v(>jt+DvlLs8pq5HyUrOwD^)0E|4^Sr2^ zjvIv1Sd4%S02z5N%;9{BfO0Vp=ZMxo`=x}1Rm^|Ds9|m2PaBx>7e%)6+%XI1UJqDg#2KZ;6mob{R{T7D!odQi zN12`Q=HhGj7Cmo2=KwqmJ{}=?k1^e84d*OVUp<(LwDVJ z#!%5RjNt0NB;D)EdlK$p)6TN8f3NkrPkQ6Zd^Sd4FkI99(rv-vvBxjqDr0GNVoO&s znNpg;Sq4dMhxtcG-U}+ibCoRL^9hN9UFECqOnJa|U2&3k!wfrE!H zqOU^x(R1DJlSHYan}+WT{k86m@byY3Zz=r}4x7`0qKvi~j4jUfie)e=th{FUz8B%< zko}2c+91vR>G*D;1=}6|oegdeS*l3Me>c5js8x?Z_{%84vT9J>3U3&KTuWhjCfnef z#!m^~OLu$oGo*2lRYu#b`VI<9+B64+ksEQTQkUYpv-4ho8T(MZJeKdmg{QF*+z?qlk~NK3gJ%S2X+#8 zPW5M(ujGtdp1{lzQJ5I-n1|}79r*e`+wsMx`=ogw>JJ|^7pa%bm&WzF{VqgBMdRKn zVbZu-_q~c^M~~nS>vL)P>re!0I0@`!zU`W#YWnY#QD%o!DjNePY?)PcF!|NbUy`{x#X#YIj#eez=mk0oud zLh`1+qkZ8OG(k?pFlt^(Z8P@$@9*gwegYrmIp(}lqeIldF}Uo`Ut{@bP{9-XN3F0~ zv+&-%f5aA^KIy4Ei)WzL4aN9*S7OdJF8(IyO$8MdC#B7Z-LKt=O$V#6Engwc0}0oW z(U=(Lc!C1g{1bV2^@UGxoI6!EF33dCx72GN!9(gd@QHmHR8d1t4_BT>3Y^3^l)*X# zag&MPkPiew7h*vO7qMjaTr@fqp|@35@63Gu<9NMPII8GQHjYHZD{!rm(3Pw1G3Df%2llw?TPj%KH{ z+~hMgmr2+DJ=20Fvz^y+B-$WMyykw48#@L|hB$VNRW18baQv7Lt|z6x-d>;$g<{4^ z{F<_$E^06e!iTx()x?b+`?6(74{XHlKdmJWC$PSV_^Wjozw}RE|IPEQbeRI7QYIOqUPcdWvtM8#wAArnD@5OCB=v07eFhas7Vd)$*@-~*EqTI73 zso+Mz@RT5oA5@8VAEs&c<*PArWF)TYn@-EM_#j}0)mniQxwU8=M+>gdFeEa7VKE$j z#Y3Xn5W4YUJipaWYboC7ns;35{;+uu)_;76YZ52VpfVm&db}H+;feht_>eM8%+o6& z_=`rXmrVrbWa0Xdi zUw97t+K0ow7^>rx-9GHUzt(CgX~v5EOsccta=FJ zhX!L>?yI=(H@HXpA)fi|4jeD8=Rz+Sb02&S*IrkTY57O+tGB=JHBF^ldpj-}REP1$ z{)`nbZFApm=Ypx73m@rJ(^LX8Hv#rnT!*yu!N_YRcdV|Ju1%SohC%d&iQfMuKFD{R z+yo{JKY7;aEZ2F`{`ZKeflkw|J)|gmcVshOgV;o;Tkz;EQ4*V z!LJ@D#hSNv;HcL#>`^ax(i1ZKPWAC;H-*ei~ z7(N2SmpzEbmdwWHs+}k+^7u+#!oX_|ALp0p<6Iz_Op7SQcAJ^zpuQ?d+!d=a+?I!# zMO*O1%^#w0@J(2}WEiekd^>L4@fbcRO2P2O?CYYg`>HP}MCt$g0!0*HzP0xVwUb`t z@|C*Wlu7p%hIXeCDMxEU+|V5dnh5IJZZ`Qv}%=HK3o z#y@_74Eo^}@)=COcQxk6m14M)zbO<$Fmc&ZOka2j(hsf0t6S<&*+^wLJWldK6}WB` zxNh^{IwWKS);y@koi8~yS_DE0Dp(1N)?iiRKI9$$A2Rm?DBZ7T}axugcn;@#r zx4rb5q^L985nDWrx9)iv2df&8Cl*INEK>CCD_3F4u?O+uTW!**kR&%A`WvqM$@LhO zf0*>TiHl%I(S`<*XIzaQA1=nB*lLaP8r+ zdUx5lD-e>k9=aWWcGIhwRt(#J`!p)-dc#{Vug}AZ{SKU` z-u?{64x5d;pJ_&s(`OKIUCTJZTWn5ui<0$g@wZPESQizKxj*|qEUA1RTYm8JaTYR8 z>|8mE;Kd`N+Of3t75vxT+t5k@+#N5Do^daRg*9P#$#%SO--pPJnvayRsd(`Al~}&( zF=-?F+=dJ>aKk4X??3S(>^z~fM-1ZGW6w(D_>tWBn@PFwDgKh%it>67-P`RYIQ(Tf zj(;7%jrKFcYkStqi{UC-@o8q`>P5*2IPy7)vnh*-`KcW6CrufNL20UPc!mehaktEe zp)eEQJa#jlBY%lo@=J_OiNLK_&&IoXJE%BY(A&5OC+BYtzAxm)6|rR);Vn0=T88Nh zrn==ub(4o4J-t4Q?`S=VIa4q$upWgCv|4ex|0`0iL+a?ESpCpE4AH4zh}WQ+{0)U? zv2Suyr-eYT`P+yYwCpWL#Ao;59~0livdd;6n%2GkGVWZ`fa;njxfl!2fiXWHYd+i# zJAA6P*AAu;Evw3n`ths8jh)oA8?Qi&7*3bycbIP5UCR4Y0}w*v{u&7`&}pD z?z`>vY%d@G{`v%_rH#RWyjCPBnj~L}31bqGq^d&Z{#_7es)Cg$Xg;gtDW-a4DpCXX zpoR4wXT83~dgN!_yQnos<;IMjKEN%73+O`(&ZY@Qj-i#I#H)Xy% zjJy>yVTq1FVj^*^m?+_D%ggn_)mU1E9b10Dl6%Htbl4FJ$%amzVb@&>3k}7jv14I7 z@DFS`UVzLZ(spNNr->7gI4B6I5&8J;-`S|EX+sM)RusH8`=hPMeJ%~UL4}x*NMTK7 zOq4c#2{QKo8UM+sMQM|bQ6n3nsH}x@R3Z|2;!;I}$||R?q>+nK3r`<~`C=>Su+>jl zcGT$jSJ89`KkV6yEt~fttGO9Q;$L5%h&ok_cYRe3)L_zpFHlNrS2o+H zMQk!?wPP`9vJuDL*n|9xV$K5xsJp+}hq%i_keD_OGZZ_dc`P+gH<++qQW8>7dV@5x0sN#;U%5`XCbGYb=$1S zDXW2LNH~Jbu}J15C?_A$@BI)hJe@5uHKU#uufiC@SW}CgtoPQ-d74b$NuDc{XOJES zguv2NPUY6cGjfq%T7saQ5x62UN^&c)*pd;f9p}b1kM0339wcyW7#@b1S5Ckb)gBz6 zxuC>fiG!kPKR$hT1CAUoJS|+U1_w@m*vID)HJaANW3lRO7W_~($+|x@jO01R*sT- zJ~Ooj*`?L6r&6g84=3MOkncN6ZRRdCXMBQ>vzk#uG7QjjGgsdL^|)jVpot}zIig85 z5fjpFDE{IgijN(4^X&t>4#6~TpbxH|^F*%>^~Kx9ACQ-si>wN&C4P7#9xS%qj1Fk@*N>6PP`=8K<hy3zf?~!qlCR%H}w*!q0joi5A=5;5$IMa1wO9skI^YGpqpWzry znOmDHnT9YDwdz5f2MR}8FW0r_=v74bHMjLtgcw0`}a*P4M2tML0QsQ%mbw zAvdherM_~bxR`QdxLa>@g^b$v`$61O^+ffORm%jb}CJ6p{a+(^t#ie0HMXIlBpVg2JSi26DLTvPmS5PUzAC!yYlu1magn^&+1FmQe)3Dzp)}hB(qe3BMF9C*(4cghYC3NgX5?XHiKnuf z^T(ANIq4A`n`n=?#&NNx;5P0|2|j$ZRIC$ zoSQ9*7!6{raooIAp)BJVvMTG5-AiRz>bUctcB>V}=2mEij>Cu)&S&wxFz*s_gSxHg ziFXl}AdST*P|<96#Iaypgf>0{JMmZZIf!TAD#pedw3X$8(^e`rwq-Cg!W}oSbb`kQ zXehf9iJt;C;ujKcAm4W4%Gd+`xOV7_tD(+b`OMUGu@JegdG6xe{PDxpbsskkT1hkB z^lEOdhd7B9w6EdjvG}tSXG3EXR4FtOCVz`}-megS4R%%Lc=eZYTFN+a^4VEj4&OVw z_~a$y!p(uGj~v993!@QP59LlN5wNb8u8iz7<<=~n9`xWTGZ55a`JEiQ6v^$(~!davAR2I&DaG#5h z;c2rlAk>Jk)=KQ$bqofv*yXU#=)%Vv*D1@0>q0+V$#E^!2#cWUZ8TA-;3;0>0^E52 zJfx+@LVV>YnJ7Jal;(Kg>o)9 zs-$tzD#ZRhKKqNqWY*QC-tY|9J>9?3uS^{V?T8!k;1ic3nE{ftt|KG*XKLCq(Oi_* zeHESlO5fk)%P@R=8Xoy>^#aS9YFaj!P61c3 z>*+MTreb_5C^&m@k{2Zcf)Ws(b`w@VJ{PgXM~V+9?xLx=u90TnRMyW}VW2TZ0;x41 z2Fcf~gqkK8iwU=<_~A-Lwx>lAHXPxpv+?kng_4Zpv}EzZRhYE*v@+*)iU87O>b1E2 zfjJmEBnrVU=F5!+rIoHp-v+vdhy~U2A-R+ zY9wa(VCBb)Yn(MU)WgI-cX}ZEag^sA#~Y7+andIH^98CY^Dr#gj`3|f@c15Xp!x8* z{@n8mqi=SGwy)j$3SRsu3zeEw%)aYctQs>5k-NWwmM5IOS-zcLhxc0^{a9P9!3Yc;gWIW@*eTC?7L2by3`p+7g^Gac z=GV%xcGQ{aTH3*z%V&D`1}+2K1Yv(b>7W5 zgrt=w`C`rA8@CaAFL{P{tDU`9C?XlyCjvJ;xD3JH{|+DR&2#6jRm}YvZkcGu!r0F4 z?Cv{}Qfwd=Tt5$^2Po0{@niV8%Ws`0bRn~D!<&n|xsbE2q$!9^O2@hx_wx(K#$avs z+gSN-z9X-98(nR@aQ%V4y$5Q&=N;dZwneM~5pscU<2^22;_3|c<VU%opYi7_V@Vhr#Z+Lf`ie~MI4Q1=QW?Ybw&@`7dzkfB2sHRP38aZWfXPbXTG@h zq)OK{_WC2JJ&=Kih0tPg$T{)MoI%w1yn0s{Um`FSH?6!9am8;VW6N>;zYV2Q6(aaz z+K70pne1DmuZ*Kr0%hk-Pe00-4TCXr_!dca`rgsaCodV-Oj%d)GS?LaPKz4%ZC(f!ExlPee6So`~U8t4YIeZ#l7X3dXr{al9646kKStp48X zKImWKWW-MP$PH!n0o3Jq$&Ef};a~2j}F`SK`+=g@Fie;F{9i#y#cHz}xJN+{EBe2PY%-pN7aK;#H zD&9}?tZqEQ7@R~{Mz?lz(C3YUFzFS44uyq2fMw+f&TYYBn&{FZ##zKd#DX8T>_Plo zo_Njs5$>$3!;x2tQNloB9hR#?*wJL00ft!&lCReHCz>!dS|R1KbXF?8m@O8Xi#H&W zQOc7;%F##%SJ$bZbb*~pyLBf{WG~0$ph1{4bvWKUdceC1&wFmnpN~cC@LKf+sNMM% zUK{)iT)Fgi448BRc>7&!F6W}Xy_#0B)u^pk;nGo45WIgsA27{V2hGE(8yKK1=rG## zj?^SwjbF=?wMjQG$GFNp*pZu$&1D7;uEB%5$5pD7G(g%iI38+O%}~jpGTc&zqdAS3 zKWiZ-Zmma9MXAT{*89$~qo^*AM=|}O7hIEqy_?JF=T7ScsjoL9C~K7Z`!2~77^i~^oep0Zav`&v~QhhkILeQm7D#|A3SeeK^YAhWj@gDeJzGw#H~ zNuyEHdK4|ij>Ww_bWuSj3V->8JKN90&NvpL4 zs#irYqZGu(1|ggQk!s3vXd*6n%NQi4jKg(HheM-q9ia-J(TNy2oTttQzs5T+?)T82 z(-p<-@6JF&CZoa&SNaDP^|o(a45ZI-?V_Ddzm7+smVVw0)>ii|(+D=y@)?96FnAo6 zUpWeKAx9vxx}CAY*aKF}J{&voW6Vn(fgtkn_cM?8O>=ZXu=7vEsqCAgrRxqeWh7}} z%q~Z5rARMnk!Wbyj8RA*9YQfyT1ndU7WaNH=Z?op%@^N$M=@E+LA9j&`OHohf;{nV)KWfYr1Z+D91y4UC;s;~Z z@-c{Trb;^-eeAn7JaVJ@;8&Cz2Rw4aNEgOd#u4ZyPDfd~!J(x&c+_~PgY}3Liwfa$>dxa_hmwpE3>~UN;*fL+R|zcfkMQH< zwHZvB-NU^C_pSZvjmR∨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 diff --git a/content/ko/docs/setup/production-environment/windows/intro-windows-in-kubernetes.md b/content/ko/docs/setup/production-environment/windows/intro-windows-in-kubernetes.md deleted file mode 100644 index 18234f97aa0..00000000000 --- a/content/ko/docs/setup/production-environment/windows/intro-windows-in-kubernetes.md +++ /dev/null @@ -1,1358 +0,0 @@ ---- - - - - - -title: 쿠버네티스에서 윈도우 컨테이너 -content_type: concept -weight: 65 ---- - - - -{{< note >}} -본 문서의 영어 원문([Windows containers in Kubernetes](/docs/setup/production-environment/windows/intro-windows-in-kubernetes/))은 변경되었습니다. - -최신 내용은 원문을 통해 확인하시기 바랍니다. - -본 문서에 대한 갱신은 기여를 통해 진행되며, 갱신이 완료되면 해당 알림은 제거됩니다. -{{< /note >}} - -윈도우 애플리케이션은 많은 조직에서 실행되는 서비스 및 -애플리케이션의 상당 부분을 구성한다. -[윈도우 컨테이너](https://aka.ms/windowscontainers)는 프로세스와 패키지 종속성을 -캡슐화하는 현대적인 방법을 제공하여, 데브옵스(DevOps) -사례를 더욱 쉽게 사용하고 윈도우 애플리케이션의 클라우드 네이티브 패턴을 따르도록 한다. -쿠버네티스는 사실상의 표준 컨테이너 오케스트레이터가 되었으며, -쿠버네티스 1.14 릴리스에는 쿠버네티스 클러스터의 윈도우 노드에서 윈도우 -컨테이너 스케줄링을 위한 프로덕션 지원이 포함되어 있어, 광범위한 윈도우 애플리케이션 생태계가 -쿠버네티스의 강력한 기능을 활용할 수 있다. 윈도우 기반 애플리케이션과 -리눅스 기반 애플리케이션에 투자한 조직은 워크로드를 관리하기 위해 -별도의 오케스트레이터를 찾을 필요가 없으므로, -운영 체제와 관계없이 배포 전반에 걸쳐 -운영 효율성이 향상된다. - - - -## 쿠버네티스의 윈도우 컨테이너 - -쿠버네티스에서 윈도우 컨테이너 오케스트레이션을 활성화하려면, 기존 -리눅스 클러스터에 윈도우 노드를 포함한다. 쿠버네티스의 -{{< glossary_tooltip text="파드" term_id="pod" >}}에서 윈도우 컨테이너를 스케줄링하는 것은 -리눅스 기반 컨테이너를 스케줄링하는 것과 유사하다. - -윈도우 컨테이너를 실행하려면, 쿠버네티스 클러스터에 리눅스를 -실행하는 컨트롤 플레인 노드와 사용자의 워크로드 요구에 따라 윈도우 또는 리눅스를 -실행하는 워커가 있는 여러 운영 체제가 포함되어 있어야 한다. 윈도우 -서버 2019는 윈도우에서 -[쿠버네티스 노드](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/architecture.md#the-kubernetes-node)를 -활성화하는 유일한 윈도우 운영 체제이다(kubelet, -[컨테이너 런타임](https://docs.microsoft.com/ko-kr/virtualization/windowscontainers/deploy-containers/containerd) -및 kube-proxy 포함). 윈도우 배포 채널에 대한 자세한 설명은 -[Microsoft 문서](https://docs.microsoft.com/ko-kr/windows-server/get-started-19/servicing-channels-19)를 참고한다. - -[마스터 컴포넌트](/ko/docs/concepts/overview/components/)를 포함한 -쿠버네티스 컨트롤 플레인은 -리눅스에서 계속 실행된다. -윈도우 전용 쿠버네티스 클러스터는 계획이 없다. - -이 문서에서 윈도우 컨테이너에 대해 이야기할 때 -프로세스 격리된 윈도우 컨테이너를 의미한다. -[Hyper-V 격리](https://docs.microsoft.com/ko-kr/virtualization/windowscontainers/manage-containers/hyperv-container)가 -있는 윈도우 컨테이너는 향후 릴리스로 계획되어 있다. - -## 지원되는 기능 및 제한 - -### 지원되는 기능 - -#### 윈도우 OS 버전 지원 - -쿠버네티스의 윈도우 운영 체제 지원은 다음 표를 -참조한다. 단일 이기종 쿠버네티스 클러스터에는 윈도우 및 -리눅스 워커 노드가 모두 있을 수 있다. 윈도우 컨테이너는 윈도우 노드에서, -리눅스 컨테이너는 리눅스 노드에서 스케줄되어야 한다. - -| 쿠버네티스 버전 | 윈도우 서버 LTSC 릴리스 | 윈도우 서버 SAC 릴리스 | -| --- | --- | --- | --- | -| *Kubernetes v1.20* | Windows Server 2019 | Windows Server ver 1909, Windows Server ver 2004 | -| *Kubernetes v1.21* | Windows Server 2019 | Windows Server ver 2004, Windows Server ver 20H2 | -| *Kubernetes v1.22* | Windows Server 2019 | Windows Server ver 2004, Windows Server ver 20H2 | - -지원 모델을 포함한 다양한 윈도우 서버 -서비스 채널에 대한 정보는 -[윈도우 서버 서비스 채널](https://docs.microsoft.com/ko-kr/windows-server/get-started-19/servicing-channels-19)에서 확인할 수 있다. - -모든 윈도우 고객이 앱의 운영 체제를 자주 업데이트하는 것은 -아니다. 애플리케이션 업그레이드를 위해서는 클러스터에 새 노드를 -업그레이드하거나 도입하는 것이 필요하다. 이 문서에서 -쿠버네티스에서 실행되는 컨테이너의 운영 체제를 업그레이드하기로 선택한 -고객을 위해 새 운영 체제 버전에 대한 지원을 추가할 때의 가이드와 -단계별 지침을 제공한다. 이 가이드에는 클러스터 노드와 함께 사용자 애플리케이션을 -업그레이드하기 위한 권장 업그레이드 절차가 포함된다. -윈도우 노드는 현재 리눅스 노드와 동일한 방식으로 쿠버네티스 -[버전-차이(skew) 정책](/ko/releases/version-skew-policy/)(노드 대 컨트롤 플레인 -버전 관리)을 준수한다. - - -윈도우 서버 호스트 운영 체제에는 -[윈도우 서버](https://www.microsoft.com/ko-kr/cloud-platform/windows-server-pricing) -라이선스가 적용된다. 윈도우 컨테이너 이미지에는 -[윈도우 컨테이너에 대한 추가 사용 조건](https://docs.microsoft.com/en-us/virtualization/windowscontainers/images-eula)이 적용된다. - -프로세스 격리가 포함된 윈도우 컨테이너에는 엄격한 호환성 규칙이 있으며, -[여기서 호스트 OS 버전은 컨테이너 베이스 이미지 OS 버전과 일치해야 한다](https://docs.microsoft.com/ko-kr/virtualization/windowscontainers/deploy-containers/version-compatibility). -일단 쿠버네티스에서 Hyper-V 격리가 포함된 윈도우 컨테이너를 지원하면, -제한 및 호환성 규칙이 변경될 것이다. - -#### 퍼즈(Pause) 이미지 {#pause-image} - -쿠버네티스는 윈도우 지원을 포함하는 다중 아키텍처 이미지를 유지보수한다. -쿠버네티스 v1.22의 경우 권장 퍼즈 이미지는 `k8s.gcr.io/pause:3.5`이다. -[소스 코드](https://github.com/kubernetes/kubernetes/tree/master/build/pause)는 -GitHub에서 찾을 수 있다. - -Microsoft는 리눅스, 윈도우 amd64를 지원하는 다중 아키텍처 이미지를 `mcr.microsoft.com/oss/kubernetes/pause:3.5`에서 유지보수하고 있다. -이 이미지는 쿠버네티스가 유지 관리하는 이미지와 동일한 소스코드에서 생성되었지만, 모든 윈도우 바이너리는 Microsoft에 의해 서명된 [인증 코드](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/authenticode)이다. -프로덕션 환경에서 서명된 바이너리가 필요한 경우, Microsoft가 유지 관리하는 이미지를 사용하는 것을 권장한다. - -#### 컴퓨트 - -API 및 kubectl의 관점에서, 윈도우 컨테이너는 -리눅스 기반 컨테이너와 거의 같은 방식으로 작동한다. 그러나 -[제한 섹션](#제한)에 요약된 주요 기능에는 -몇 가지 눈에 띄는 차이점이 있다. - -윈도우에서 주요 쿠버네티스 요소는 리눅스와 동일한 방식으로 작동한다. 이 -섹션에서는, 주요 워크로드 인에이블러(enabler) 일부와 이들이 윈도우에 매핑되는 방법에 -대해 설명한다. - -* [파드](/ko/docs/concepts/workloads/pods/) - - 파드는 쿠버네티스의 기본 빌딩 블록이다 - 쿠버네티스 오브젝트 모델에서 - 생성하고 배포하는 가장 작고 간단한 단위. 동일한 파드에 - 윈도우 및 리눅스 컨테이너를 배포할 수 없다. 파드의 모든 컨테이너는 - 단일 노드로 스케줄되며 각 노드는 특정 플랫폼 및 - 아키텍처를 나타낸다. 다음과 같은 파드 기능, 속성 및 - 이벤트가 윈도우 컨테이너에서 지원된다. - - * 프로세스 분리 및 볼륨 공유 기능을 갖춘 파드 당 하나 또는 여러 개의 컨테이너 - * 파드 상태 필드 - * 준비성(readiness) 및 활성 프로브(liveness probe) - * postStart 및 preStop 컨테이너 라이프사이클 이벤트 - * 컨피그맵(ConfigMap), 시크릿(Secrets): 환경 변수 또는 볼륨으로 - * EmptyDir - * 명명된 파이프 호스트 마운트 - * 리소스 제한 -* [컨트롤러](/ko/docs/concepts/workloads/controllers/) - - 쿠버네티스 컨트롤러는 파드의 의도한 상태(desired state)를 처리한다. 윈도우 - 컨테이너에서 지원되는 워크로드 컨트롤러는 다음과 같다. - - * 레플리카셋(ReplicaSet) - * 레플리케이션컨트롤러(ReplicationController) - * 디플로이먼트(Deployment) - * 스테이트풀셋(StatefulSet) - * 데몬셋(DaemonSet) - * 잡(Job) - * 크론잡(CronJob) -* [서비스](/ko/docs/concepts/services-networking/service/) - - 쿠버네티스 서비스는 논리적인 파드 집합과 그것에(마이크로 서비스라고도 함) - 접근하는 정책을 정의하는 추상화 개념이다. 상호-운영 체제 - 연결을 위해 서비스를 사용할 수 있다. 윈도우에서 서비스는 - 다음의 유형, 속성 및 기능을 활용할 수 있다. - - * 서비스 환경 변수 - * 노드포트(NodePort) - * 클러스터IP(ClusterIP) - * 로드밸런서(LoadBalancer) - * ExternalName - * 헤드리스 서비스(Headless services) - -파드, 컨트롤러 및 서비스는 쿠버네티스에서 윈도우 워크로드를 -관리하는데 중요한 요소이다. 그러나 그 자체로는 동적 클라우드 네이티브 환경에서 -윈도우 워크로드의 적절한 수명 주기 관리를 수행하기에 -충분하지 않다. 다음 기능에 대한 지원이 추가되었다. - -* 파드와 컨테이너 메트릭 -* Horizontal Pod Autoscaler 지원 -* kubectl Exec -* 리소스쿼터(Resource Quotas) -* 스케쥴러 선점(preemption) - -#### 컨테이너 런타임 - -##### Docker EE - -{{< feature-state for_k8s_version="v1.14" state="stable" >}} - -Docker EE-basic 19.03 이상은 모든 윈도우 서버 버전에 대해 권장되는 -컨테이너 런타임이다. 이것은 kubelet에 포함된 dockershim 코드와 함께 작동한다. - -##### CRI-ContainerD - -{{< feature-state for_k8s_version="v1.20" state="stable" >}} - -{{< glossary_tooltip term_id="containerd" text="ContainerD" >}} 1.4.0+는 -윈도우 쿠버네티스 노드의 컨테이너 런타임으로도 사용할 수 있다. - -[윈도우에 ContainerD 설치](/ko/docs/setup/production-environment/container-runtimes/#containerd-설치) -방법을 확인한다. - -#### 퍼시스턴트 스토리지(Persistent Storage) - -쿠버네티스 [볼륨](/ko/docs/concepts/storage/volumes/)을 사용하면 -데이터 지속성(persistence) 및 파드 볼륨 공유 요구 사항이 있는 복잡한 애플리케이션을 -쿠버네티스에 배포할 수 있다. 특정 스토리지 백엔드 또는 -프로토콜과 관련된 퍼시스턴트 볼륨 관리에는 -볼륨 프로비저닝/디-프로비저닝/크기 조정, 쿠버네티스 노드에 볼륨 -연결/분리, 데이터를 유지해야 하는 파드의 개별 컨테이너에 볼륨 -마운트/분리와 같은 작업이 포함된다. 특정 스토리지 백엔드 또는 -프로토콜에 대해 이러한 볼륨 관리 작업을 -구현하는 코드는 쿠버네티스 볼륨 -[플러그인](/ko/docs/concepts/storage/volumes/#볼륨-유형들)의 형태로 제공된다. 다음과 같은 -광범위한 쿠버네티스 볼륨 플러그인 클래스가 윈도우에서 지원된다. - -##### 인-트리(In-tree) 볼륨 플러그인 - -인-트리 볼륨 플러그인과 관련된 코드는 핵심 쿠버네티스 -코드 베이스의 일부로 제공된다. 인-트리 볼륨 플러그인 배포는 -추가 스크립트를 설치하거나 별도의 컨테이너화된 플러그인 컴포넌트를 -배포할 필요가 없다. 이러한 플러그인들은 -볼륨 프로비저닝/디-프로비저닝, 스토리지 백엔드 볼륨 크기 조정, 쿠버네티스 노드에 -볼륨 연결/분리, 파드의 개별 컨테이너에 볼륨 마운트/분리를 -처리할 수 있다. 다음의 인-트리 플러그인은 윈도우 노드를 지원한다. - -* [awsElasticBlockStore](/ko/docs/concepts/storage/volumes/#awselasticblockstore) -* [azureDisk](/ko/docs/concepts/storage/volumes/#azuredisk) -* [azureFile](/ko/docs/concepts/storage/volumes/#azurefile) -* [gcePersistentDisk](/ko/docs/concepts/storage/volumes/#gcepersistentdisk) -* [vsphereVolume](/ko/docs/concepts/storage/volumes/#vspherevolume) - -##### FlexVolume 플러그인 - -[FlexVolume](/ko/docs/concepts/storage/volumes/#flexVolume) -플러그인과 관련된 코드는 아웃-오브-트리(out-of-tree) 스크립트 또는 호스트에 직접 배포해야 하는 -바이너리로 제공된다. FlexVolume 플러그인은 쿠버네티스 노드에 볼륨 -연결/분리 및 파드의 개별 컨테이너에 볼륨 마운트/분리를 -처리한다. FlexVolume 플러그인과 관련된 퍼시스턴트 볼륨의 -프로비저닝/디-프로비저닝은 일반적으로 FlexVolume 플러그인과는 별도의 외부 -프로비저너를 통해 처리될 수 있다. 호스트에서 -powershell 스크립트로 배포된 다음의 FlexVolume -[플러그인](https://github.com/Microsoft/K8s-Storage-Plugins/tree/master/flexvolume/windows)은 -윈도우 노드를 지원한다. - -* [SMB](https://github.com/microsoft/K8s-Storage-Plugins/tree/master/flexvolume/windows/plugins/microsoft.com~smb.cmd) -* [iSCSI](https://github.com/microsoft/K8s-Storage-Plugins/tree/master/flexvolume/windows/plugins/microsoft.com~iscsi.cmd) - -##### CSI 플러그인 - -{{< feature-state for_k8s_version="v1.22" state="stable" >}} - -{{< glossary_tooltip text="CSI" term_id="csi" >}} 플러그인과 -관련된 코드는 일반적으로 컨테이너 이미지로 배포되고 데몬셋(DaemonSets) -및 스테이트풀셋(StatefulSets)과 같은 -표준 쿠버네티스 구성을 사용하여 배포되는 아웃-오브-트리 스크립트 및 -바이너리로 제공된다. CSI 플러그인은 쿠버네티스에서 볼륨 프로비저닝/디-프로비저닝, 볼륨 -크기 조정, 쿠버네티스 노드에 볼륨 연결/분리, 파드의 개별 컨테이너에 볼륨 -마운트/분리, 스냅샷 및 복제를 사용하여 퍼시스턴트 데이터 백업/복원과 같은 -다양한 볼륨 관리 작업을 처리한다. - -CSI 노드 플러그인(특히 블록 디바이스 또는 공유 파일시스템으로 노출된 -퍼시스턴트 볼륨과 관련된 플러그인)은 디스크 장치 스캔, 파일 시스템 마운트 등과 같은 -다양한 특권이 필요한(privileged) 작업을 수행해야 -한다. 이러한 작업은 호스트 운영 체제마다 다르다. 리눅스 워커 -노드의 경우 컨테이너화된 CSI 노드 플러그인은 일반적으로 특권을 가진 -컨테이너로 배포된다. 윈도우 워커 노드의 경우 컨테이너화된 -CSI 노드 플러그인에 대한 특권이 필요한 작업은 커뮤니티에서 관리되고, -각 윈도우 노드에 사전 설치되어야 하는 독립형(stand-alone) 바이너리인 -[csi-proxy](https://github.com/kubernetes-csi/csi-proxy)를 사용하여 지원된다. 자세한 -내용은 배포하려는 CSI 플러그인의 배포 가이드를 -참조한다. - -윈도우 노드에서 CSI 노드 플러그인은 일반적으로 로컬 스토리지 작업을 처리하는 -커뮤니티에서 관리하는 [csi-proxy](https://github.com/kubernetes-csi/csi-proxy)에 의해 노출된 API를 호출한다. - -설치에 대한 자세한 내용은 윈도우 CSI 플러그인을 -배포할 환경의 배포 가이드를 참고한다. -또한 다음 [설치 단계](https://github.com/kubernetes-csi/csi-proxy#installation)를 참고할 수도 있다. - -#### 네트워킹 - -윈도우 컨테이너용 네트워킹은 -[CNI 플러그인](/ko/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)을 통해 노출된다. -윈도우 컨테이너는 네트워킹과 관련하여 가상 머신과 유사하게 -작동한다. 각 컨테이너에는 Hyper-V 가상 스위치(vSwitch)에 연결된 -가상 네트워크 어댑터(vNIC)가 있다. 호스트 네트워킹 서비스(HNS)와 -호스트 컴퓨팅 서비스(HCS)는 함께 작동하여 컨테이너를 만들고 -컨테이너 vNIC을 네트워크에 연결한다. HCS는 컨테이너 관리를 -담당하는 반면 HNS는 다음과 같은 네트워킹 리소스 관리를 -담당한다. - -* 가상 네트워크(vSwitch 생성 포함) -* 엔드포인트 / vNIC -* 네임스페이스 -* 정책(패킷 캡슐화, 로드 밸런싱 규칙, ACL, NAT 규칙 등) - -다음의 서비스 사양 유형이 지원된다. - -* NodePort -* ClusterIP -* LoadBalancer -* ExternalName - -##### 네트워크 모드 - -윈도우는 L2bridge, L2tunnel, Overlay, Transparent 및 -NAT의 다섯 가지 네트워킹 드라이버/모드를 지원한다. 윈도우와 리눅스 워커 노드가 -있는 이기종 클러스터에서는 윈도우와 리눅스 모두에서 호환되는 네트워킹 -솔루션을 선택해야 한다. 윈도우에서 다음과 같은 out-of-tree 플러그인이 지원되며 -각 CNI 사용 시 권장 사항이 있다. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
네트워크 드라이버설명컨테이너 패킷 수정네트워크 플러그인네트워크 플러그인 특성
L2bridge컨테이너는 외부 vSwitch에 연결된다. 컨테이너는 - 언더레이 네트워크에 연결된다. 하지만 인그레스/이그레스시에 재작성되기 - 때문에 물리적 네트워크가 컨테이너 MAC을 학습할 필요가 없다. - - MAC은 호스트 MAC에 다시 쓰여지고, IP는 HNS OutboundNAT 정책을 사용하여 - 호스트 IP에 다시 쓰여질 수 있다. - - win-bridge, - Azure-CNI, - Flannel 호스트 게이트웨이는 win-bridge를 사용한다. - - win-bridge는 L2bridge 네트워크 모드를 사용하고, - 컨테이너를 호스트의 언더레이에 연결하여 최상의 성능을 제공한다. - 노드 간 연결을 위해 사용자 정의 경로(user-defined routes, UDR)가 필요하다. -
L2Tunnel - 이것은 l2bridge의 특별한 케이스이지만 Azure에서만 사용된다. 모든 패킷은 - SDN 정책이 적용되는 가상화 호스트로 전송된다. - - MAC 재작성되고, 언더레이 네트워크 상에서 IP가 보인다. - - Azure-CNI - - Azure-CNI를 사용하면 컨테이너를 Azure vNET과 통합할 수 있으며, - Azure Virtual Network에서 - 제공하는 기능 집합을 활용할 수 있다. - 예를 들어, Azure 서비스에 안전하게 연결하거나 Azure NSG를 사용한다. - azure-cni - 예제를 참고한다. -
오버레이(쿠버네티스에서 윈도우용 오버레이 네트워킹은 알파 단계에 있음) - 컨테이너에는 외부 vSwitch에 연결된 vNIC이 제공된다. 각 오버레이 - 네트워크는 사용자 지정 IP 접두사로 정의된 자체 IP 서브넷을 가져온다. 오버레이 - 네트워크 드라이버는 VXLAN 캡슐화를 사용한다. - - 외부 헤더로 캡슐화된다. - - Win-overlay, - Flannel VXLAN (win-overlay 사용) - - win-overlay는 가상 컨테이너 네트워크를 호스트의 - 언더레이에서 격리하려는 경우(예: 보안 상의 이유로) 사용해야 한다. 데이터 센터의 IP에 - 제한이 있는 경우, (다른 VNID 태그가 있는) 다른 오버레이 - 네트워크에 IP를 재사용할 수 있다. 이 옵션을 사용하려면 - 윈도우 서버 2019에서 KB4489899가 - 필요하다. -
- Transparent(ovn-kubernetes의 특수한 유스케이스) - - 외부 vSwitch가 필요하다. 컨테이너는 논리적 네트워크(논리적 스위치 및 라우터)를 - 통해 파드 내 통신을 가능하게 하는 외부 vSwitch에 - 연결된다. - - 패킷은 - GENEVE, - STT 터널링을 통해 - 캡슐화되는데, 동일한 호스트에 있지 않은 파드에 도달하기 위한 터널링을 한다.
패킷은 ovn 네트워크 - 컨트롤러에서 제공하는 터널 메타데이터 정보를 통해 전달되거나 삭제된다. -
- NAT는 north-south 통신(데이터 센터와 클라이언트, 네트워크 상의 데이터 센터 외부와의 통신)을 위해 수행된다. -
- ovn-kubernetes - - Ansible을 통해 배포한다. - 분산 ACL은 쿠버네티스 정책을 통해 적용할 수 있다. IPAM을 지원한다. - kube-proxy 없이 로드 밸런싱을 수행할 수 있다. NAT를 수행할 때 - iptables/netsh를 사용하지 않고 수행된다. -
NAT (쿠버네티스에서 사용되지 않음) - 컨테이너에는 내부 vSwitch에 연결된 vNIC이 제공된다. DNS/DHCP는 - WinNAT라는 - 내부 컴포넌트를 사용하여 제공된다. - - MAC 및 IP는 호스트 MAC/IP에 다시 작성된다. - - nat - - 완전성을 위해 여기에 포함되었다. -
- -위에서 설명한대로 [플란넬(Flannel)](https://github.com/coreos/flannel) CNI -[메타 플러그인](https://github.com/containernetworking/plugins/tree/master/plugins/meta/flannel)은 -[VXLAN 네트워크 백엔드](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#vxlan) -(**alpha 지원**, win-overlay에 위임) 및 -[host-gateway network backend](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#host-gw) -(안정적인 지원, win-bridge에 위임)를 통해 -[윈도우](https://github.com/containernetworking/plugins/tree/master/plugins/meta/flannel#windows-support-experimental)에서도 -지원된다. 이 플러그인은 자동 노드 서브넷 -임대 할당과 HNS 네트워크 생성을 위해 윈도우 (Flanneld)에서 -Flannel 데몬과 함께 작동하도록 참조 CNI 플러그인 (win-overlay, win-bridge) -중 하나에 대한 위임을 지원한다. 이 플러그인은 자체 -구성 파일 (cni.conf)을 읽고, 이를 FlannelD 생성하는 subnet.env 파일의 환경 변수와 -함께 집계한다. 이후 네트워크 연결을 위한 -참조 CNI 플러그인 중 하나에 위임하고 노드 할당 서브넷을 포함하는 올바른 -구성을 IPAM 플러그인 (예: 호스트-로컬)으로 -보낸다. - -노드, 파드, 서비스 오브젝트의 경우 TCP/UDP 트래픽에 대해 다음 -네트워크 흐름이 지원된다. - -* 파드 -> 파드(IP) -* 파드 -> 파드(Name) -* 파드 -> 서비스(Cluster IP) -* 파드 -> 서비스(PQDN, 단 "."이 없는 경우에만) -* 파드 -> 서비스(FQDN) -* 파드 -> External(IP) -* 파드 -> External(DNS) -* 노드 -> 파드 -* 파드 -> 노드 - -##### IP 주소 관리(IPAM) - -윈도우에서는 다음 IPAM 옵션이 지원된다. - -* [호스트-로컬](https://github.com/containernetworking/plugins/tree/master/plugins/ipam/host-local) -* HNS IPAM(Inbox 플랫폼 IPAM, 이것은 IPAM이 설정되지 않은 경우 폴백(fallback)이다) -* [Azure-vnet-ipam](https://github.com/Azure/azure-container-networking/blob/master/docs/ipam.md)(azure-cni 전용) - -##### 로드 밸런싱과 서비스 - -윈도우에서는 다음 설정을 사용하여 서비스 및 로드 밸런싱 동작을 -구성할 수 있다. - -{{< table caption="윈도우 서비스 구성" >}} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
기능설명지원되는 쿠버네티스 버전지원되는 윈도우 OS 빌드활성화하는 방법
세션 어피니티 - 특정 클라이언트의 연결이 매번 동일한 파드로 - 전달되도록 한다. - v1.20 이상 - 윈도우 서버 vNext Insider Preview Build 19551 (또는 그 이상) - - service.spec.sessionAffinity를 "ClientIP"로 설정 -
직접 서버 반환 (DSR) - IP 주소 수정 및 LBNAT가 컨테이너 vSwitch 포트에서 직접 - 발생하는 로드 밸런싱 모드. 서비스 트래픽은 소스 IP가 원래 파드 IP로 - 설정된 상태로 도착한다. - v1.20 이상 - 윈도우 서버 2019 - - kube-proxy에서 다음 플래그를 설정한다. - --feature-gates="WinDSR=true" --enable-dsr=true -
대상 보존(Preserve-Destination) - 서비스 트래픽의 DNAT를 스킵하여, 백엔드 파드에 도달하는 패킷에서 대상 - 서비스의 가상 IP를 보존한다. 또한 노드-노드 전달을 비활성화한다. - v1.20 이상윈도우 서버, 버전 1903 (또는 그 이상) - 서비스 어노테이션에서 "preserve-destination": "true"를 설정하고 - kube-proxy에서 DSR을 활성화한다. -
IPv4/IPv6 이중 스택 네트워킹 - 클러스터 내/외부 기본 IPv4-to-IPv4 통신과 함께 - IPv6-to-IPv6 통신 - v1.19 이상윈도우 서버, 버전 2004 (또는 그 이상) - IPv4/IPv6 이중 스택을 참고한다. -
클라이언트 IP 보존 - 인그레스 트래픽의 소스 IP가 유지되도록 한다. 또한 - 노드-노드 전달을 비활성화한다. - v1.20 이상윈도우 서버, 버전 2019 (또는 그 이상) - service.spec.externalTrafficPolicy를 "Local"로 설정하고 - kube-proxy에서 DSR을 활성화한다. -
- -{{< /table >}} - -#### IPv4/IPv6 이중 스택 - -`IPv6DualStack` [기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)를 -사용하여 `l2bridge` 네트워크에 IPv4/IPv6 이중 스택 네트워킹을 활성화할 수 있다. 자세한 내용은 -[IPv4/IPv6 이중 스택 활성화](/ko/docs/concepts/services-networking/dual-stack/#ipv4-ipv6-이중-스택-활성화)를 -참조한다. - -윈도우에서 쿠버네티스와 함께 IPv6를 사용하려면 윈도우 서버 버전 2004 -(커널 버전 10.0.19041.610) 이상이 필요하다. - -윈도우의 오버레이(VXLAN) 네트워크는 현재 이중 스택 네트워킹을 지원하지 않는다. - -### 제한 - -윈도우는 쿠버네티스 아키텍처 및 컴포넌트 매트릭스에서 워커 -노드로만 지원된다. 즉, 쿠버네티스 클러스터에는 항상 리눅스 마스터 노드가 반드시 -포함되어야 하고, 0개 이상의 리눅스 워커 노드 및 0개 이상의 윈도우 -워커 노드가 포함된다. - -#### 자원 관리 - -리눅스 cgroup은 리눅스에서 리소스 제어를 위한 파드 경계로 사용된다. -컨테이너는 네트워크, 프로세스 및 파일시스템 격리를 위해 해당 -경계 내에 생성된다. cgroups API는 cpu/io/memory 통계를 수집하는 데 사용할 수 있다. -반대로 윈도우는 시스템 네임스페이스 필터가 있는 컨테이너별로 잡(Job) -오브젝트를 사용하여 컨테이너의 모든 프로세스를 포함하고 호스트와의 -논리적 격리를 제공한다. 네임스페이스 필터링 없이 윈도우 컨테이너를 -실행할 수 있는 방법은 없다. 즉, 시스템 권한은 호스트 컨텍스트에서 삽입될(assert) 수 없으므로 -권한이 있는(privileged) 컨테이너는 윈도우에서 사용할 수 없다. 보안 계정 -매니져(Security Account Manager, SAM)가 분리되어 있으므로 -컨테이너는 호스트의 ID를 가정할 수 없다. - -#### 자원 예약 - -##### 메모리 예약 - -윈도우에는 리눅스에는 있는 메모리 부족 프로세스 킬러가 없다. 윈도우는 -모든 사용자-모드 메모리 할당을 항상 가상 메모리처럼 처리하며, 페이지파일이 -필수이다. 결과적으로 윈도우에서는 리눅스에서 발생할 수 있는 -메모리 부족 상태에 도달하지 않으며, 프로세스는 메모리 부족(out of memory, OOM) 종료를 -겪는 대신 디스크로 페이징한다. 메모리가 오버프로비저닝되고 -모든 물리 메모리가 고갈되면 페이징으로 인해 성능이 저하될 수 있다. - -kubelet 파라미터 `--kubelet-reserve` 를 사용하여 메모리 사용량을 -합리적인 범위 내로 유지할 수 있으며, `--system-reserve` 를 사용하여 -노드(컨테이너 외부)의 메모리 사용량을 예약할 수 있다. 이들을 사용하면 그만큼 -[노드 할당(NodeAllocatable)](/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable)은 줄어든다. - -워크로드를 배포할 때, 컨테이너에 리소스 제한을 -걸어라(제한만 설정하거나, 제한이 요청과 같아야 함). 이 또한 NodeAllocatable에서 차감되며, -메모리가 꽉 찬 노드에 스케줄러가 파드를 할당하지 않도록 제한한다. - -오버프로비저닝을 방지하는 가장 좋은 방법은 윈도우, 도커, 그리고 -쿠버네티스 프로세스를 위해 최소 2GB 이상의 시스템 예약 메모리로 -kubelet을 설정하는 것이다. - -##### CPU 예약 - -윈도우, 도커, 그리고 다른 쿠버네티스 호스트 프로세스가 이벤트에 -잘 응답할 수 있도록, CPU의 일정 비율을 예약하는 것이 -좋다. 이 값은 윈도우 노드에 있는 CPU 코어 수에 -따라 조정해야 한다. 이 비율을 결정하려면, 각 노드의 -최대 파드 밀도(density)를 관찰하고, 시스템 서비스의 CPU -사용량을 모니터링하여 워크로드 요구사항을 충족하는 값을 선택해야 한다. - -kubelet 파라미터 `--kubelet-reserve` 를 사용하여 CPU 사용량을 -합리적인 범위 내로 유지할 수 있으며, `--system-reserve` 를 사용하여 -노드 (컨테이너 외부) 의 CPU 사용량을 예약할 수 있다. 이들을 사용하면 그만큼 -[노드 할당(NodeAllocatable)](/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable)은 줄어든다. - -#### 기능 제한 - -* TerminationGracePeriod: 구현되지 않음 -* 단일 파일 매핑: CRI-ContainerD로 구현 예정 -* 종료 메시지: CRI-ContainerD로 구현 예정 -* 특권을 가진(Privileged) 컨테이너: 현재 윈도우 컨테이너에서 지원되지 않음 -* HugePages: 현재 윈도우 컨테이너에서 지원되지 않음 -* 기존 노드 문제 감지기는 리눅스 전용이며 특권을 가진 - 컨테이너가 필요하다. 윈도우에서 특권을 가진 컨테이너를 지원하지 않기 때문에 - 일반적으로 윈도우에서 이 기능이 사용될 것으로 예상하지 않는다. -* 공유 네임스페이스의 모든 기능이 지원되는 것은 아니다. (자세한 내용은 - API 섹션 참조). - -#### 각 플래그의 리눅스와의 차이점 - -윈도우 노드에서의 kubelet 플래그의 동작은 아래에 설명된 대로 다르게 동작한다. - -* `--kubelet-reserve`, `--system-reserve`, `--eviction-hard` 플래그는 - Node Allocatable 업데이트 - -* `--enforce-node-allocable`을 사용한 축출(Eviction)은 구현되지 않았다. - -* `--eviction-hard`와 `--eviction-soft`를 사용한 축출은 구현되지 않았다. - -* MemoryPressure 조건은 구현되지 않았다. - -* kubelet이 취한 OOM 축출 조치가 없다. - -* 윈도우 노드에서 실행되는 Kubelet에는 메모리 제한이 없다. - `--kubelet-reserve`와 `--system-reserve`는 호스트에서 실행되는 kubelet 또는 - 프로세스에 제한을 설정하지 않는다. 이는 호스트의 kubelet 또는 프로세스가 - node-allocatable 및 스케줄러 외부에서 메모리 리소스 부족을 유발할 수 있음을 - 의미한다. - -* kubelet 프로세스의 우선 순위를 설정하는 추가 플래그는 - `--windows-priorityclass`라는 윈도우 노드에서 사용할 수 있다. 이 플래그를 사용하면 - kubelet 프로세스가 윈도우 호스트에서 실행중인 다른 프로세스와 비교할 때 더 많은 CPU 시간 - 슬라이스을 얻을 수 있다. 허용되는 값과 그 의미에 대한 자세한 내용은 - [윈도우 우선순위 클래스](https://docs.microsoft.com/en-us/windows/win32/procthread/scheduling-priorities#priority-class)에서 - 확인할 수 있다. - kubelet이 항상 충분한 CPU주기를 갖도록 하려면 - 이 플래그를 `ABOVE_NORMAL_PRIORITY_CLASS` 이상으로 설정하는 것이 좋다. - -#### 스토리지 - -윈도우에는 컨테이너 계층을 마운트하고 NTFS를 기반으로 하는 복제 파일시스템을 -만드는 레이어드(layered) 파일시스템 드라이버가 있다. 컨테이너의 모든 파일 경로는 -해당 컨테이너의 컨텍스트 내에서만 확인된다. - -* 도커 볼륨 마운트는 개별 파일이 아닌 컨테이너의 - 디렉터리만 대상으로 할 수 있다. 이 제한은 CRI-containerD에는 존재하지 않는다. - -* 볼륨 마운트는 파일이나 디렉터리를 호스트 파일시스템으로 다시 - 투영할 수 없다. - -* 읽기 전용 파일시스템은 윈도우 레지스트리 및 SAM 데이터베이스에 항상 - 쓰기 접근이 필요하기 때문에 지원되지 않는다. 그러나 읽기 전용 - 볼륨은 지원된다. - -* 볼륨 사용자 마스크(user-masks) 및 권한은 사용할 수 없다. SAM은 - 호스트와 컨테이너 간에 공유되지 않기 때문에 이들 간에 매핑이 없다. 모든 - 권한은 컨테이너 컨텍스트 내에서 해결된다. - -결과적으로, 다음 스토리지 기능은 윈도우 노드에서 지원되지 않는다. - -* 볼륨 하위 경로(subpath) 마운트. 전체 볼륨만 윈도우 컨테이너에 마운트할 수 있다. -* 시크릿에 대한 하위 경로 볼륨 마운트 -* 호스트 마운트 프로젝션 -* DefaultMode(UID/GID 종속성에 기인함) -* 읽기 전용 루트 파일시스템. 매핑된 볼륨은 여전히 읽기 전용을 지원한다. -* 블록 디바이스 매핑 -* 저장 매체로서의 메모리 -* uui/guid, 사용자별 리눅스 파일시스템 권한과 같은 파일시스템 기능 -* NFS 기반 스토리지/볼륨 지원 -* 마운트된 볼륨 확장(resizefs) - -#### 네트워킹 {#네트워킹-제한} - -윈도우 컨테이너 네트워킹은 리눅스 네트워킹과 몇 가지 중요한 면에서 -다르다. [윈도우 컨테이너 네트워킹에 대한 Microsoft 문서](https://docs.microsoft.com/ko-kr/virtualization/windowscontainers/container-networking/architecture)에는 -추가 세부 정보와 배경이 포함되어 있다. - -윈도우 호스트 네트워킹 서비스와 가상 스위치는 네임스페이스를 -구현하고 파드 또는 컨테이너에 필요한 가상 NIC을 만들 수 있다. 그러나 -DNS, 라우트, 메트릭과 같은 많은 구성은 리눅스에서와 같이 /etc/... 파일이 -아닌 윈도우 레지스트리 데이터베이스에 저장된다. 컨테이너의 -윈도우 레지스트리는 호스트 레지스트리와 별개이므로 호스트에서 -컨테이너로 /etc/resolv.conf를 매핑하는 것과 같은 개념은 리눅스에서와 -동일한 효과를 갖지 않는다. 해당 컨테이너의 컨텍스트에서 실행되는 윈도우 API를 -사용하여 구성해야 한다. 따라서 CNI 구현에서는 파일 매핑에 의존하는 -대신 HNS를 호출하여 네트워크 세부 정보를 파드 또는 컨테이너로 -전달해야 한다. - -다음 네트워킹 기능은 윈도우 노드에서 지원되지 않는다. - -* 윈도우 파드에서는 호스트 네트워킹 모드를 사용할 수 없다. - -* 노드 자체에서 로컬 NodePort 접근은 실패한다. (다른 노드 또는 - 외부 클라이언트에서는 가능) - -* 노드에서 서비스 VIP에 접근하는 것은 향후 윈도우 서버 릴리스에서 - 사용할 수 있다. - -* 한 서비스는 최대 64개의 백엔드 파드 또는 고유한 목적지 IP를 지원할 수 있다. - -* kube-proxy의 오버레이 네트워킹 지원은 베타 기능이다. 또한 - 윈도우 서버 2019에 [KB4482887](https://support.microsoft.com/ko-kr/help/4482887/windows-10-update-kb4482887)을 - 설치해야 한다. - -* 비-DSR 모드의 로컬 트래픽 정책 - -* 오버레이 네트워크에 연결된 윈도우 컨테이너는 - IPv6 스택을 통한 통신을 지원하지 않는다. 이 네트워크 드라이버가 IPv6 주소를 - 사용하고 kubelet, kube-proxy 및 CNI 플러그인에서 후속 쿠버네티스 작업을 - 사용할 수 있도록 하는데 필요한 뛰어난 윈도우 플랫폼 작업이 있다. - -* win-overlay, win-bridge, Azure-CNI 플러그인을 통해 - ICMP 프로토콜을 사용하는 아웃바운드 통신. 특히, 윈도우 데이터 플레인 - ([VFP](https://www.microsoft.com/en-us/research/project/azure-virtual-filtering-platform/))은 - ICMP 패킷 치환을 지원하지 않는다. 이것은 다음을 의미한다. - - * 동일한 네트워크(예: ping을 통한 파드 간 통신) 내의 목적지로 전달되는 - ICMP 패킷은 예상대로 제한 없이 작동한다. - - * TCP/UDP 패킷은 예상대로 제한 없이 작동한다. - - * 원격 네트워크를 통과하도록 지정된 ICMP 패킷(예: ping을 통한 - 파드에서 외부 인터넷으로의 통신)은 치환될 수 없으므로 - 소스로 다시 라우팅되지 않는다. - - * TCP/UDP 패킷은 여전히 치환될 수 있기 때문에 - `ping `을 `curl `으로 대체하여 - 외부와의 연결을 디버깅할 수 있다. - -해당 기능은 쿠버네티스 v1.15에 추가되었다. - -* `kubectl port-forward` - -##### CNI 플러그인 - -* 윈도우 참조 네트워크 플러그인 win-bridge와 win-overlay는 - 현재 "CHECK" 구현 누락으로 인해 [CNI 사양](https://github.com/containernetworking/cni/blob/master/SPEC.md) - v0.4.0을 구현하지 않는다. - -* Flannel VXLAN CNI는 윈도우에서 다음과 같은 제한이 있다. - - 1. 노드-파드 연결은 설계상 불가능하다. Flannel v0.12.0(또는 그 이상)이 - 있는 로컬 파드에서만 가능하다. - - 1. VNI 4096와 UDP 4789 포트 사용은 제한된다. VNI 제한은 - 작업 중이며 향후 릴리스(오픈 소스 flannel 변경)에서 - 구현될 것이다. 이러한 파라미터에 대한 자세한 내용은 공식 - [Flannel VXLAN](https://github.com/coreos/flannel/blob/master/Documentation/backends.md#vxlan) - 백엔드 문서를 참고한다. - -##### DNS {#dns-limitations} - -* ClusterFirstWithHostNet은 DNS에서 지원되지 않는다. 윈도우는 - '.'이 있는 모든 이름을 FQDN으로 처리하고 PQDN 확인을 건너뛴다. - -* 리눅스에서는 PQDN을 확인하려고 할 때 사용되는 DNS 접미사 목록이 - 있다. 윈도우에서는 해당 파드의 네임스페이스(예: mydns.svc.cluster.local)와 - 연결된 DNS 접미사인 DNS 접미사 1개만 있다. - 윈도우는 FQDN과 서비스 또는 해당 접미사만으로 확인할 수 있는 이름을 확인할 수 - 있다. 예를 들어, 디폴트 네임스페이스에서 생성된 파드에는 DNS - 접미사 `default.svc.cluster.local`이 있다. 윈도우 파드에서는 - `kubernetes.default.svc.cluster.local` 및 `kubernetes`를 모두 확인할 수 - 있지만 `kubernetes.default` 또는 `kubernetes.default.svc`와 같은 중간 항목은 확인할 수 없다. - -* 윈도우에서는 사용할 수 있는 여러 가지의 DNS 리졸버(resolver)가 있다. 이들은 - 약간 다른 동작을 제공하므로, 이름 쿼리 확인을 위해 `Resolve-DNSName` 유틸리티를 - 사용하는 것이 좋다. - -##### IPv6 - -윈도우의 쿠버네티스는 단일 스택 "IPv6 전용" 네트워킹을 지원하지 않는다. -그러나 단일 제품군 서비스를 사용하는 파드와 노드에 대한 이중 스택 IPv4/IPv6 네트워킹이 -지원된다. -자세한 내용은 [IPv4/IPv6 이중 스택 네트워킹](#ipv4ipv6-이중-스택)을 참고한다. - -##### 세션 어피니티(affinity) - -`service.spec.sessionAffinityConfig.clientIP.timeoutSeconds`를 사용하는 -윈도우 서비스의 최대 세션 고정(sticky) 시간 설정은 지원되지 않는다. - -##### 보안 - -시크릿(Secret)은 노드의 볼륨(리눅스의 tmpfs/in-memory와 -비교)에 일반 텍스트로 작성된다. 이는 고객이 두 가지 작업을 수행해야 함을 의미한다. - -1. 파일 ACL을 사용하여 시크릿 파일 위치를 보호한다. -1. [BitLocker](https://docs.microsoft.com/ko-kr/windows/security/information-protection/bitlocker/bitlocker-how-to-deploy-on-windows-server)를 - 사용한 볼륨-레벨 암호화를 사용한다. - -[RunAsUsername](/ko/docs/tasks/configure-pod-container/configure-runasusername/)은 -컨테이너 프로세스를 노드 기본 사용자로 실행하기 위해 윈도우 파드 또는 -컨테이너에 지정할 수 있다. 이것은 -[RunAsUser](/ko/docs/concepts/security/pod-security-policy/#사용자-및-그룹)와 거의 동일하다. - -SELinux, AppArmor, Seccomp, 기능(POSIX 기능)과 같은 -리눅스 특유의 파드 시큐리티 컨텍스트 권한은 지원하지 않는다. - -또한 이미 언급했듯이 특권을 가진 컨테이너는 윈도우에서 지원되지 -않는다. - -#### API - -대부분의 Kubernetes API가 윈도우에서 작동하는 방식은 차이가 없다. -중요한 차이점은 OS와 컨테이너 런타임의 차이로 -귀결된다. 특정 상황에서 파드 또는 컨테이너와 같은 워크로드 API의 -일부 속성은 리눅스에서 구현되고 윈도우에서 실행되지 않는다는 가정 하에 -설계되었다. - -높은 수준에서 이러한 OS 개념은 다르다. - -* ID - 리눅스는 정수형으로 표시되는 userID(UID) 및 groupID(GID)를 - 사용한다. 사용자와 그룹 이름은 정식 이름이 아니다. UID+GID에 대한 - `/etc/groups` 또는 `/etc/passwd`의 별칭일 뿐이다. 윈도우는 윈도우 - 보안 계정 관리자(Security Account Manager, SAM) 데이터베이스에 - 저장된 더 큰 이진 보안 식별자(SID)를 사용한다. 이 데이터베이스는 호스트와 - 컨테이너 간에 또는 컨테이너들 간에 공유되지 않는다. - -* 파일 퍼미션 - 윈도우는 권한 및 UUID+GID의 비트 마스크(bitmask) 대신 - SID를 기반으로 하는 접근 제어 목록을 사용한다. - -* 파일 경로 - 윈도우의 규칙은 `/` 대신 `\`를 사용하는 것이다. Go IO - 라이브러리는 두 가지 파일 경로 분리자를 모두 허용한다. 하지만, 컨테이너 - 내부에서 해석되는 경로 또는 커맨드 라인을 설정할 때 `\`가 필요할 수 - 있다. - -* 신호(Signals) - 윈도우 대화형(interactive) 앱은 종료를 다르게 처리하며, 다음 중 - 하나 이상을 구현할 수 있다. - - * UI 스레드는 `WM_CLOSE`를 포함하여 잘 정의된(well-defined) 메시지를 처리한다. - - * 콘솔 앱은 컨트롤 핸들러(Control Handler)를 사용하여 ctrl-c 또는 ctrl-break를 처리한다. - - * 서비스는 `SERVICE_CONTROL_STOP` 제어 코드를 수용할 수 있는 - Service Control Handler 함수를 등록한다. - -종료 코드는 0일 때 성공, 0이 아닌 경우 실패인 동일한 규칙을 따른다. -특정 오류 코드는 윈도우와 리눅스에서 다를 수 있다. 그러나 -쿠버네티스 컴포넌트(kubelet, kube-proxy)에서 전달된 종료 코드는 -변경되지 않는다. - -##### V1.Container - -* V1.Container.ResourceRequirements.limits.cpu 및 - V1.Container.ResourceRequirements.limits.memory - 윈도우는 CPU 할당에 하드 - 리밋(hard limit)을 사용하지 않는다. 대신 공유 시스템이 사용된다. 밀리코어를 - 기반으로 하는 기존 필드는 윈도우 스케줄러가 뒤따르는 상대적인 공유로 - 스케일된다. - [참고: kuberuntime/helpers_windows.go](https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/kuberuntime/helpers_windows.go), - [참고: Microsoft 문서 내 리소스 제어](https://docs.microsoft.com/ko-kr/virtualization/windowscontainers/manage-containers/resource-controls) - - * Huge page는 윈도우 컨테이너 런타임에서 구현되지 않으며, - 사용할 수 없다. 컨테이너에 대해 구성할 수 없는 - [사용자 권한(privilege) 어설트](https://docs.microsoft.com/en-us/windows/desktop/Memory/large-page-support)가 - 필요하다. - -* V1.Container.ResourceRequirements.requests.cpu 및 - V1.Container.ResourceRequirements.requests.memory - 노드의 사용 가능한 - 리소스에서 요청(requests)을 빼서, 노드에 대한 오버 프로비저닝을 방지하는데 사용할 수 - 있다. 그러나 오버 프로비저닝된 노드에서 리소스를 보장하는 데는 - 사용할 수 없다. 운영자가 오버 프로비저닝을 완전히 피하려는 경우 - 모범 사례로 모든 컨테이너에 적용해야 한다. - -* V1.Container.SecurityContext.allowPrivilegeEscalation - 윈도우에서는 - 불가능하며, 어떤 기능도 연결되지 않는다. - -* V1.Container.SecurityContext.Capabilities - POSIX 기능은 윈도우에서 - 구현되지 않는다. - -* V1.Container.SecurityContext.privileged - 윈도우는 특권을 가진 컨테이너를 - 지원하지 않는다. - -* V1.Container.SecurityContext.procMount - 윈도우에는 /proc 파일시스템이 없다. - -* V1.Container.SecurityContext.readOnlyRootFilesystem - 윈도우에서는 불가능하며, - 레지스트리 및 시스템 프로세스가 컨테이너 내부에서 실행되려면 쓰기 권한이 - 필요하다. - -* V1.Container.SecurityContext.runAsGroup - 윈도우에서는 불가능하며, GID 지원이 없다. - -* V1.Container.SecurityContext.runAsNonRoot - 윈도우에는 root 사용자가 - 없다. 가장 가까운 항목은 노드에 존재하지 않는 아이덴티티(identity)인 - ContainerAdministrator이다. - -* V1.Container.SecurityContext.runAsUser - 윈도우에서는 불가능하며, 정수값으로의 UID - 지원이 없다. - -* V1.Container.SecurityContext.seLinuxOptions - 윈도우에서는 불가능하며, SELinux가 없다. - -* V1.Container.terminationMessagePath - 윈도우가 단일 파일 매핑을 지원하지 - 않는다는 점에서 몇 가지 제한이 있다. 기본값은 /dev/termination-log이며, 기본적으로 윈도우에 존재하지 않기 때문에 - 작동한다. - -##### V1.Pod - -* V1.Pod.hostIPC, v1.pod.hostpid - 윈도우에서 호스트 네임스페이스 공유가 불가능하다. - -* V1.Pod.hostNetwork - 호스트 네트워크를 공유하기 위한 윈도우 OS 지원이 없다. - -* V1.Pod.dnsPolicy - ClusterFirstWithHostNet - 윈도우에서 호스트 네트워킹이 지원되지 않기 때문에 - 지원되지 않는다. - -* V1.Pod.podSecurityContext - 아래 V1.PodSecurityContext 내용을 참고한다. - -* V1.Pod.shareProcessNamespace - 이것은 베타 기능이며, 윈도우에서 구현되지 않은 - 리눅스 네임스페이스에 따라 다르다. 윈도우는 프로세스 네임스페이스 또는 - 컨테이너의 루트 파일시스템을 공유할 수 없다. 네트워크만 공유할 수 - 있다. - -* V1.Pod.terminationGracePeriodSeconds - 이것은 윈도우의 도커에서 - 완전히 구현되지 않았다. - [참조](https://github.com/moby/moby/issues/25982)의 내용을 참고한다. 현재 동작은 - `ENTRYPOINT` 프로세스가 `CTRL_SHUTDOWN_EVENT`로 전송된 다음, 윈도우가 기본적으로 5초를 - 기다린 후, 마지막으로 정상적인 윈도우 종료 동작을 사용하여 모든 프로세스를 - 종료하는 것이다. 5초 기본값은 실제로 - [컨테이너 내부](https://github.com/moby/moby/issues/25982#issuecomment-426441183) - 윈도우 레지스트리에 있으므로 컨테이너를 빌드할 때 재정의 할 수 있다. - -* V1.Pod.volumeDevices - 이것은 베타 기능이며, 윈도우에서 구현되지 - 않는다. 윈도우는 원시 블록 장치(raw block device)를 파드에 연결할 수 없다. - -* V1.Pod.volumes - EmptyDir, 시크릿, 컨피그맵, HostPath - 모두 작동하며 - TestGrid에 테스트가 있다. - - * V1.emptyDirVolumeSource - 노드 기본 매체는 윈도우의 디스크이다. - 윈도우에는 내장 RAM 디스크가 없기 때문에 메모리는 지원되지 않는다. - -* V1.VolumeMount.mountPropagation - 마운트 전파(propagation)는 윈도우에서 지원되지 않는다. - -##### V1.PodSecurityContext - -PodSecurityContext 필드는 윈도우에서 작동하지 않는다. 참조를 위해 여기에 -나열한다. - -* V1.PodSecurityContext.SELinuxOptions - SELinux는 윈도우에서 사용할 수 없다. - -* V1.PodSecurityContext.RunAsUser - 윈도우에서는 사용할 수 없는 UID를 제공한다. - -* V1.PodSecurityContext.RunAsGroup - 윈도우에서는 사용할 수 없는 GID를 제공한다. - -* V1.PodSecurityContext.RunAsNonRoot - 윈도우에는 root 사용자가 없다. 가장 - 가까운 항목은 노드에 존재하지 않는 아이덴티티인 - ContainerAdministrator이다. - -* V1.PodSecurityContext.SupplementalGroups - 윈도우에서는 사용할 수 없는 GID를 제공한다. - -* V1.PodSecurityContext.Sysctls - 이것들은 리눅스 sysctl 인터페이스의 - 일부이다. 윈도우에는 이에 상응하는 것이 없다. - -#### 운영 체제 버전 제한 - -윈도우에는 호스트 OS 버전이 컨테이너 베이스 이미지 OS 버전과 일치해야 하는 -엄격한 호환성 규칙이 있다. 윈도우 서버 2019의 컨테이너 -운영 체제가 있는 윈도우 컨테이너만 지원된다. 윈도우 컨테이너 이미지 버전의 일부 -이전 버전과의 호환성을 가능하게 하는 컨테이너의 Hyper-V 격리는 -향후 릴리스로 계획되어 있다. - -## 도움 받기 및 트러블슈팅 {#troubleshooting} - -쿠버네티스 클러스터 트러블슈팅을 위한 기본 -도움말은 -[이 섹션](/ko/docs/tasks/debug/debug-cluster/)에서 먼저 찾아야 한다. 이 -섹션에는 몇 가지 추가 윈도우 관련 트러블슈팅 도움말이 포함되어 있다. -로그는 쿠버네티스에서 트러블슈팅하는데 중요한 요소이다. 다른 -기여자로부터 트러블슈팅 지원을 구할 때마다 이를 포함해야 -한다. SIG-Windows -[로그 수집에 대한 기여 가이드](https://github.com/kubernetes/community/blob/master/sig-windows/CONTRIBUTING.md#gathering-logs)의 지침을 따른다. - -* start.ps1이 성공적으로 완료되었는지 어떻게 알 수 있는가? - - kubelet, kube-proxy 및 (Flannel을 네트워킹 솔루션으로 - 선택한 경우) 노드에서 실행 중인 flanneld 호스트 에이전트 프로세스를 - 확인할 수 있어야 하는데, 별도의 PowerShell 윈도우에서 실행 중인 로그가 표시된다. 또한 - 윈도우 노드는 쿠버네티스 클러스터에서 "Ready"로 조회되어야 - 한다. - -* 백그라운드에서 서비스로 실행되도록 쿠버네티스 노드 프로세스를 구성할 수 있는가? - - Kubelet 및 kube-proxy는 이미 기본 윈도우 서비스로 실행되도록 - 구성되어 있으며, 실패(예: 프로세스 충돌) 시 서비스를 - 자동으로 다시 시작하여 복원력(resiliency)을 - 제공한다. 이러한 노드 컴포넌트를 서비스로 구성하기 위한 - 두 가지 옵션이 있다. - - * 네이티브 윈도우 서비스 - - Kubelet와 kube-proxy는 `sc.exe`를 사용하여 네이티브 윈도우 서비스로 실행될 수 있다. - - ```powershell - # 두 개의 개별 명령으로 kubelet 및 kube-proxy에 대한 서비스 생성 - sc.exe create <컴포넌트_명> binPath= "<바이너리_경로> --service <다른_인자>" - - # 인자에 공백이 포함된 경우 이스케이프 되어야 한다. - sc.exe create kubelet binPath= "C:\kubelet.exe --service --hostname-override 'minion' <다른_인자>" - - # 서비스 시작 - Start-Service kubelet - Start-Service kube-proxy - - # 서비스 중지 - Stop-Service kubelet (-Force) - Stop-Service kube-proxy (-Force) - - # 서비스 상태 질의 - Get-Service kubelet - Get-Service kube-proxy - ``` - - * nssm.exe 사용 - - 또한 언제든지 [nssm.exe](https://nssm.cc/)와 같은 - 대체 서비스 관리자를 사용하여 백그라운드에서 이러한 프로세스(flanneld, kubelet, - kube-proxy)를 실행할 수 있다. 이 - [샘플 스크립트](https://github.com/Microsoft/SDN/tree/master/Kubernetes/flannel/register-svc.ps1)를 사용하여 - 백그라운드에서 윈도우 서비스로 실행하기 위해 `nssm.exe`를 활용하여 kubelet, kube-proxy, - `flanneld.exe`를 등록할 수 있다. - - ```powershell - register-svc.ps1 -NetworkMode <네트워크 모드> -ManagementIP <윈도우 노드 IP> -ClusterCIDR <클러스터 서브넷> -KubeDnsServiceIP -LogDir <로그 위치 디렉터리> - ``` - 파라미터 설명은 아래와 같다. - - - `NetworkMode`: 네트워크 모드 l2bridge(flannel host-gw, - 기본값이기도 함) 또는 네트워크 솔루션으로 선택한 오버레이(flannel vxlan) - - `ManagementIP`: 윈도우 노드에 할당된 IP 주소. `ipconfig`를 사용하여 - 찾을 수 있다. - - `ClusterCIDR`: 클러스터 서브넷 범위. (기본값 10.244.0.0/16) - - `KubeDnsServiceIP`: 쿠버네티스 DNS 서비스 IP (기본값 10.96.0.10) - - `LogDir`: kubelet 및 kube-proxy 로그가 각각의 출력 파일로 - 리다이렉션되는 디렉터리(기본값 C:\k) - - 위에 언급된 스크립트가 적합하지 않은 경우, 다음 예제를 사용하여 - `nssm.exe`를 수동으로 구성할 수 있다. - - flanneld.exe를 등록한다. - - ```powershell - nssm install flanneld C:\flannel\flanneld.exe - nssm set flanneld AppParameters --kubeconfig-file=c:\k\config --iface= --ip-masq=1 --kube-subnet-mgr=1 - nssm set flanneld AppEnvironmentExtra NODE_NAME= - nssm set flanneld AppDirectory C:\flannel - nssm start flanneld - ``` - - kubelet.exe를 등록한다. - - ```powershell - nssm install kubelet C:\k\kubelet.exe - nssm set kubelet AppParameters --hostname-override= --v=6 --pod-infra-container-image=k8s.gcr.io/pause:3.5 --resolv-conf="" --allow-privileged=true --enable-debugging-handlers --cluster-dns= --cluster-domain=cluster.local --kubeconfig=c:\k\config --hairpin-mode=promiscuous-bridge --image-pull-progress-deadline=20m --cgroups-per-qos=false --log-dir= --logtostderr=false --enforce-node-allocatable="" --network-plugin=cni --cni-bin-dir=c:\k\cni --cni-conf-dir=c:\k\cni\config - nssm set kubelet AppDirectory C:\k - nssm start kubelet - ``` - - kube-proxy.exe를 등록한다(l2bridge / host-gw). - - ```powershell - nssm install kube-proxy C:\k\kube-proxy.exe - nssm set kube-proxy AppDirectory c:\k - nssm set kube-proxy AppParameters --v=4 --proxy-mode=kernelspace --hostname-override=--kubeconfig=c:\k\config --enable-dsr=false --log-dir= --logtostderr=false - nssm.exe set kube-proxy AppEnvironmentExtra KUBE_NETWORK=cbr0 - nssm set kube-proxy DependOnService kubelet - nssm start kube-proxy - ``` - - kube-proxy.exe를 등록한다(overlay / vxlan). - - ```powershell - nssm install kube-proxy C:\k\kube-proxy.exe - nssm set kube-proxy AppDirectory c:\k - nssm set kube-proxy AppParameters --v=4 --proxy-mode=kernelspace --feature-gates="WinOverlay=true" --hostname-override= --kubeconfig=c:\k\config --network-name=vxlan0 --source-vip= --enable-dsr=false --log-dir= --logtostderr=false - nssm set kube-proxy DependOnService kubelet - nssm start kube-proxy - ``` - - - 초기 트러블슈팅을 위해 [nssm.exe](https://nssm.cc/)에서 - 다음 플래그를 사용하여 stdout 및 stderr을 출력 파일로 리다이렉션할 수 있다. - - ```powershell - nssm set AppStdout C:\k\mysvc.log - nssm set AppStderr C:\k\mysvc.log - ``` - - 자세한 내용은 공식 [nssm 사용](https://nssm.cc/usage) 문서를 참고한다. - -* 내 윈도우 파드에 네트워크 연결이 없다. - - 가상 머신을 사용하는 경우, 모든 VM 네트워크 어댑터에서 MAC 스푸핑이 - 활성화되어 있는지 확인한다. - -* 내 윈도우 파드가 외부 리소스를 ping 할 수 없다. - - 윈도우 파드에는 현재 ICMP 프로토콜용으로 프로그래밍된 아웃바운드 - 규칙이 없다. 그러나 TCP/UDP는 지원된다. 클러스터 외부 리소스에 대한 연결을 - 시연하려는 경우, `ping `를 해당 `curl `명령으로 - 대체한다. - - 여전히 문제가 발생하는 경우, - [cni.conf](https://github.com/Microsoft/SDN/blob/master/Kubernetes/flannel/l2bridge/cni/config/cni.conf)의 - 네트워크 구성에 특별히 추가 확인이 필요하다. 언제든지 이 정적 파일을 편집할 수 있다. 구성 - 업데이트는 새로 생성된 모든 쿠버네티스 리소스에 적용된다. - - 쿠버네티스 네트워킹 요구 사항 중 - 하나([쿠버네티스 모델](/ko/docs/concepts/cluster-administration/networking/))는 - 클러스터 통신이 내부적으로 NAT 없이 발생하는 것이다. 이 요구 사항을 - 준수하기 위해 아웃바운드 NAT가 발생하지 않도록 하는 모든 통신에 대한 - [ExceptionList](https://github.com/Microsoft/SDN/blob/master/Kubernetes/flannel/l2bridge/cni/config/cni.conf#L20)가 - 있다. 그러나 - 이것은 쿼리하려는 외부 IP를 ExceptionList에서 - 제외해야 함도 의미한다. 그래야만 윈도우 파드에서 발생하는 트래픽이 제대로 SNAT 되어 - 외부에서 응답을 받는다. 이와 관련하여 `cni.conf`의 ExceptionList는 다음과 - 같아야 한다. - - ```conf - "ExceptionList": [ - "10.244.0.0/16", # 클러스터 서브넷 - "10.96.0.0/12", # 서비스 서브넷 - "10.127.130.0/24" # 관리(호스트) 서브넷 - ] - ``` - -* 내 윈도우 노드가 NodePort 서비스에 접근할 수 없다. - - 노드 자체에서는 로컬 NodePort 접근이 실패한다. 이것은 알려진 - 제약사항이다. NodePort 접근은 다른 노드 또는 외부 클라이언트에서는 가능하다. - -* 컨테이너의 vNIC 및 HNS 엔드포인트가 삭제되었다. - - 이 문제는 `hostname-override` 파라미터가 - [kube-proxy](/ko/docs/reference/command-line-tools-reference/kube-proxy/)에 - 전달되지 않은 경우 발생할 수 있다. - 이를 해결하려면 사용자는 다음과 같이 hostname을 kube-proxy에 전달해야 한다. - - ```powershell - C:\k\kube-proxy.exe --hostname-override=$(hostname) - ``` - -* 플란넬(flannel)을 사용하면 클러스터에 다시 조인(join)한 후 노드에 이슈가 발생한다. - - 이전에 삭제된 노드가 클러스터에 다시 조인될 때마다, - flannelD는 새 파드 서브넷을 노드에 할당하려고 한다. 사용자는 다음 경로에서 - 이전 파드 서브넷 구성 파일을 제거해야 한다. - - ```powershell - Remove-Item C:\k\SourceVip.json - Remove-Item C:\k\SourceVipRequest.json - ``` - -* `start.ps1`을 시작한 후, flanneld가 "Waiting for the Network - to be created"에서 멈춘다. - - 이 [이슈](https://github.com/coreos/flannel/issues/1066)에 - 대한 수많은 보고가 있다. 플란넬 네트워크의 - 관리 IP가 설정될 때의 타이밍 이슈일 가능성이 높다. 해결 - 방법은 start.ps1을 다시 시작하거나 다음과 같이 수동으로 다시 시작하는 것이다. - - ```powershell - PS C:> [Environment]::SetEnvironmentVariable("NODE_NAME", "") - PS C:> C:\flannel\flanneld.exe --kubeconfig-file=c:\k\config --iface= --ip-masq=1 --kube-subnet-mgr=1 - ``` - -* `/run/flannel/subnet.env` 누락으로 인해 윈도우 파드를 시작할 수 없다. - - 이것은 플란넬이 제대로 실행되지 않았음을 나타낸다. flanneld.exe를 - 다시 시작하거나 쿠버네티스 마스터의 - `/run/flannel/subnet.env`에서 윈도우 워커 노드의 - `C:\run\flannel\subnet.env`로 파일을 수동으로 복사할 수 있고, - `FLANNEL_SUBNET` 행을 다른 숫자로 수정한다. 예를 들어, 다음은 노드 서브넷 - 10.244.4.1/24가 필요한 경우이다. - - ```none - FLANNEL_NETWORK=10.244.0.0/16 - FLANNEL_SUBNET=10.244.4.1/24 - FLANNEL_MTU=1500 - FLANNEL_IPMASQ=true - ``` - -* 내 윈도우 노드가 서비스 IP를 사용하여 내 서비스에 접근할 수 없다. - - 이는 윈도우에서 현재 네트워킹 스택의 알려진 제약 사항이다. - 그러나 윈도우 파드는 서비스 IP에 접근할 수 있다. - -* kubelet을 시작할 때 네트워크 어댑터를 찾을 수 없다. - - 윈도우 네트워킹 스택에는 쿠버네티스 네트워킹이 작동하기 위한 - 가상 어댑터가 필요하다. 다음 명령이 (어드민 셸에서) 결과를 반환하지 - 않으면, Kubelet이 작동하는데 필요한 필수 구성 요소인 가상 네트워크 생성이 - 실패한 것이다. - - ```powershell - Get-HnsNetwork | ? Name -ieq "cbr0" - Get-NetAdapter | ? Name -Like "vEthernet (Ethernet*" - ``` - - 호스트 네트워크 어댑터가 "Ethernet"이 아닌 경우, - 종종 start.ps1 스크립트의 - [InterfaceName](https://github.com/microsoft/SDN/blob/master/Kubernetes/flannel/start.ps1#L7) - 파라미터를 수정하는 것이 좋다. 그렇지 않으면 `start-kubelet.ps1` - 스크립트의 출력을 참조하여 가상 네트워크 생성 중에 오류가 있는지 확인한다. - -* 내 파드가 "Container Creating"에서 멈췄거나 계속해서 다시 시작된다. - - 퍼즈 이미지가 OS 버전과 호환되는지 확인한다. - [지침](https://docs.microsoft.com/en-us/virtualization/windowscontainers/kubernetes/deploying-resources)에서는 - OS와 컨테이너가 모두 버전 1803이라고 가정한다. 이후 버전의 - 윈도우가 있는 경우, Insider 빌드와 같이 그에 따라 이미지를 - 조정해야 한다. 이미지는 Microsoft의 - [도커 리포지터리](https://hub.docker.com/u/microsoft/)를 참조한다. - 그럼에도 불구하고, 퍼즈 이미지 Dockerfile과 샘플 서비스는 이미지가 - :latest로 태그될 것으로 예상한다. - -* DNS 확인(resolution)이 제대로 작동하지 않는다. - - [윈도우에 대한 DNS 제한](#dns-limitations)을 확인한다. - -* `kubectl port-forward`가 "unable to do port forwarding: wincat not found"로 실패한다. - - 이는 쿠버네티스 1.15 및 퍼즈 인프라 컨테이너 - `mcr.microsoft.com/oss/kubernetes/pause:1.4.1`에서 구현되었다. - 해당 버전 또는 최신 버전을 사용해야 한다. 자체 퍼즈 - 인프라 컨테이너를 빌드하려면 - [wincat](https://github.com/kubernetes-sigs/sig-windows-tools/tree/master/cmd/wincat)을 포함해야 한다. - - 윈도우에서 포트 포워딩을 지원하려면 [퍼즈 인프라 컨테이너](#pause-image)를 이용하기 위해서 - wincat.exe가 필요하다. - 윈도우 OS 버전과 호환되는 지원되는 이미지를 사용하고 있는지 확인해야 한다. - 자신만의 퍼즈 인프라 컨테이너를 구축하려면 - [wincat](https://github.com/kubernetes/kubernetes/tree/master/build/pause/windows/wincat)을 포함해야 한다. - -* 내 윈도우 서버 노드가 프록시 뒤에 있기 때문에 내 쿠버네티스 - 설치가 실패한다. - - 프록시 뒤에 있는 경우 다음 PowerShell 환경 변수를 - 정의해야 한다. - - ```PowerShell - [Environment]::SetEnvironmentVariable("HTTP_PROXY", "http://proxy.example.com:80/", [EnvironmentVariableTarget]::Machine) - [Environment]::SetEnvironmentVariable("HTTPS_PROXY", "http://proxy.example.com:443/", [EnvironmentVariableTarget]::Machine) - ``` - -* 퍼즈(`pause`) 컨테이너란 무엇인가? - - 쿠버네티스 파드에서는 컨테이너 엔드포인트를 호스팅하기 위해 - 먼저 인프라 또는 "퍼즈" 컨테이너가 생성된다. 인프라 및 워커 컨테이너를 포함하여 - 동일한 파드에 속하는 컨테이너는 공통 네트워크 네임스페이스 및 - 엔드포인트(동일한 IP 및 포트 공간)를 공유한다. 네트워크 구성을 잃지 않고 - 워커 컨테이너가 충돌하거나 다시 시작되도록 하려면 퍼즈 컨테이너가 - 필요하다. - - 퍼즈 이미지 추천 버전을 찾기 위해서는 - [퍼즈 이미지](#pause-image)를 참고한다. - -### 추가 조사 - -이러한 단계로 문제가 해결되지 않으면, 다음을 통해 쿠버네티스의 윈도우 노드에서 -윈도우 컨테이너를 실행하는데 도움을 받을 수 있다. - -* 스택오버플로우 [윈도우 서버 컨테이너](https://stackoverflow.com/questions/tagged/windows-server-container) 주제 - -* 쿠버네티스 공식 포럼 [discuss.kubernetes.io](https://discuss.kubernetes.io/) - -* 쿠버네티스 슬랙 [#SIG-Windows Channel](https://kubernetes.slack.com/messages/sig-windows) - -## 이슈 리포팅 및 기능 요청 - -버그처럼 보이는 부분이 있거나 기능 -요청을 하고 싶다면, -[GitHub 이슈 트래킹 시스템](https://github.com/kubernetes/kubernetes/issues)을 -활용한다. -[GitHub](https://github.com/kubernetes/kubernetes/issues/new/choose)에서 이슈를 열고 -SIG-Windows에 할당할 수 있다. 먼저 이전에 보고된 이슈 목록을 검색하고 -이슈에 대한 경험을 언급하고 추가 로그를 -첨부해야 한다. SIG-Windows 슬랙은 티켓을 만들기 전에 초기 지원 및 -트러블슈팅 아이디어를 얻을 수 있는 좋은 방법이기도 하다. - -버그를 제출하는 경우, 다음과 같이 문제를 재현하는 방법에 대한 자세한 정보를 -포함한다. - -* 쿠버네티스 버전: kubectl version -* 환경 세부사항: 클라우드 공급자, OS 배포판, 네트워킹 선택 및 - 구성, 도커 버전 -* 문제를 재현하기 위한 세부 단계 -* [관련 로그](https://github.com/kubernetes/community/blob/master/sig-windows/CONTRIBUTING.md#gathering-logs) -* SIG-Windows 회원의 주의를 끌 수 있도록 `/sig windows`로 이슈에 대해 어노테이션을 달아 - 이슈에 sig/windows 태그를 지정한다. - -## {{% heading "whatsnext" %}} - -로드맵에는 많은 기능이 있다. 요약된 높은 수준의 -목록이 아래에 포함되어 있지만, -[로드맵 프로젝트](https://github.com/orgs/kubernetes/projects/8)를 보고 -[기여](https://github.com/kubernetes/community/blob/master/sig-windows/)하여 -윈도우 지원을 개선하는데 도움이 주는 것이 좋다. - -### Hyper-V 격리(isolation) - -쿠버네티스에서 윈도우 컨테이너에 대해 다음 유스케이스를 사용하려면 -Hyper-V 격리가 필요하다. - -* 추가 보안을 위해 파드 간 하이퍼바이저 기반 격리 - -* 하위 호환성을 통해 컨테이너를 다시 빌드할 필요 없이 노드에서 - 최신 윈도우 서버 버전을 실행할 수 있다. - -* 파드에 대한 특정 CPU/NUMA 설정 - -* 메모리 격리 및 예약 - -Hyper-V 격리 지원은 이후 릴리스에 추가되며 -CRI-Containerd가 필요하다. - -### kubeadm 및 클러스터 API를 사용한 배포 - -Kubeadm은 사용자가 쿠버네티스 클러스터를 배포하기 위한 사실상의 표준이 -되고 있다. kubeadm의 윈도우 노드 지원은 현재 작업 중이지만 -[여기](/ko/docs/tasks/administer-cluster/kubeadm/adding-windows-nodes/)에서 -가이드를 사용할 수 있다. -또한 윈도우 노드가 적절하게 프로비저닝되도록 클러스터 API에 -투자하고 있다. diff --git a/content/ko/docs/tasks/debug/debug-cluster/windows.md b/content/ko/docs/tasks/debug/debug-cluster/windows.md new file mode 100644 index 00000000000..7293cf1d819 --- /dev/null +++ b/content/ko/docs/tasks/debug/debug-cluster/windows.md @@ -0,0 +1,175 @@ +--- +# reviewers: +# - aravindhp +# - jayunit100 +# - jsturtevant +# - marosset +title: 윈도우 디버깅 팁 +content_type: concept +--- + + + + + +## 노드-수준 트러블슈팅 {#troubleshooting-node} + +1. 내 파드가 "Container Creating"에서 멈췄거나 계속해서 다시 시작된다. + + 퍼즈(pause) 이미지가 OS 버전과 호환되는지 확인한다. + [퍼즈 컨테이너](/ko/docs/concepts/windows/intro/#퍼즈-pause-컨테이너)에서 + 최신 / 추천 퍼즈 이미지 및 추가 정보를 확인한다. + + {{< note >}} + 컨테이너 런타임으로 containerd를 사용하고 있다면, 퍼즈 이미지는 + `config.toml` 환경 설정 파일의 `plugins.plugins.cri.sandbox_image` 필드에 명시되어 있다. + {{< /note >}} + +1. 내 파드의 상태가 `ErrImgPull` 또는 `ImagePullBackOff`이다. + + 파드가 + [호환되는](https://docs.microsoft.com/virtualization/windowscontainers/deploy-containers/version-compatibility) 윈도우 노드에 + 스케줄링되었는지 확인한다. + + 각 파드와 호환되는 노드를 찾는 방법에 대한 추가 정보는 + [이 가이드](/ko/docs/concepts/windows/user-guide/#특정-OS-워크로드를-적절한-컨테이너-호스트에서-처리하도록-보장하기)를 참고한다. + +## 네트워크 트러블슈팅 {#troubleshooting-network} + +1. 내 윈도우 파드에 네트워크 연결이 없다. + + 가상 머신을 사용하는 경우, + 모든 VM 네트워크 어댑터에 MAC 스푸핑이 **활성화**되어 있는지 확인한다. + +1. 내 윈도우 파드가 외부 리소스를 ping 할 수 없다. + + 윈도우 파드에는 현재 ICMP 프로토콜용으로 프로그래밍된 아웃바운드 규칙이 없다. + 그러나 TCP/UDP는 지원된다. + 클러스터 외부 리소스에 대한 연결을 시연하려는 경우, + `ping `를 대응되는 `curl `명령으로 대체한다. + + 여전히 문제가 발생하는 경우, + [cni.conf](https://github.com/Microsoft/SDN/blob/master/Kubernetes/flannel/l2bridge/cni/config/cni.conf)의 네트워크 구성에 특별히 추가 확인이 필요하다. + 언제든지 이 정적 파일을 편집할 수 있다. + 구성 업데이트는 새로 생성된 모든 쿠버네티스 리소스에 적용된다. + + 쿠버네티스 네트워킹 요구 + 사항([쿠버네티스 모델](/ko/docs/concepts/cluster-administration/networking/) 참조) + 중 하나는 + 클러스터 통신이 NAT 없이 내부적으로 발생해야 한다는 것이다. + 이 요구 사항을 준수하기 위해 + 아웃바운드 NAT가 발생하지 않도록 하는 + 모든 통신에 대한 [ExceptionList](https://github.com/Microsoft/SDN/blob/master/Kubernetes/flannel/l2bridge/cni/config/cni.conf#L20)가 있다. + 그러나 이것은 쿼리하려는 외부 IP를 `ExceptionList`에서 제외해야 함도 의미한다. + 그래야만 윈도우 파드에서 발생하는 트래픽이 제대로 SNAT 되어 외부에서 응답을 받는다. + 이와 관련하여 `cni.conf`의 `ExceptionList`는 다음과 같아야 한다. + + ```conf + "ExceptionList": [ + "10.244.0.0/16", # 클러스터 서브넷 + "10.96.0.0/12", # 서비스 서브넷 + "10.127.130.0/24" # 관리(호스트) 서브넷 + ] + ``` + +1. 내 윈도우 노드가 `NodePort` 서비스에 접근할 수 없다. + + 노드 자체에서는 로컬 NodePort 접근이 실패한다. 이것은 알려진 제약사항이다. + NodePort 접근은 다른 노드 또는 외부 클라이언트에서는 가능하다. + +1. 컨테이너의 vNIC 및 HNS 엔드포인트가 삭제된다. + + 이 문제는 `hostname-override` 파라미터가 + [kube-proxy](/ko/docs/reference/command-line-tools-reference/kube-proxy/)에 전달되지 않은 경우 발생할 수 있다. + 이를 해결하려면 사용자는 다음과 같이 hostname을 kube-proxy에 전달해야 한다. + + ```powershell + C:\k\kube-proxy.exe --hostname-override=$(hostname) + ``` + +1. 내 윈도우 노드가 서비스 IP를 사용하여 내 서비스에 접근할 수 없다. + + 이는 윈도우에서 현재 네트워킹 스택의 알려진 제약 사항이다. 그러나 윈도우 파드는 서비스 IP에 접근할 수 있다. + +1. kubelet을 시작할 때 네트워크 어댑터를 찾을 수 없다. + + 윈도우 네트워킹 스택에는 쿠버네티스 네트워킹이 작동하기 위한 가상 어댑터가 필요하다. + (어드민 셸에서) 다음 명령이 결과를 반환하지 않으면, + Kubelet이 작동하는 데 필요한 필수 구성 요소인 가상 네트워크 생성이 실패한 것이다. + + ```powershell + Get-HnsNetwork | ? Name -ieq "cbr0" + Get-NetAdapter | ? Name -Like "vEthernet (Ethernet*" + ``` + + 호스트 네트워크 어댑터가 "Ethernet"이 아닌 경우, 종종 `start.ps1` 스크립트의 + [InterfaceName](https://github.com/microsoft/SDN/blob/master/Kubernetes/flannel/start.ps1#L7) 파라미터를 수정하는 것이 좋다. + 그렇지 않으면 `start-kubelet.ps1` 스크립트의 출력을 참조하여 가상 네트워크 생성 중에 오류가 있는지 확인한다. + +1. DNS 해석(resolution)이 제대로 작동하지 않는다. + + 이 [섹션](/ko/docs/concepts/services-networking/dns-pod-service/#dns-windows)에서 윈도우에서의 DNS 제한을 확인한다. + +1. `kubectl port-forward`가 "unable to do port forwarding: wincat not found" 에러와 함께 실패한다. + + 이 기능은 퍼즈 인프라 컨테이너 `mcr.microsoft.com/oss/kubernetes/pause:3.6`에 + `wincat.exe`를 포함시킴으로써 쿠버네티스 1.15에서 구현되었다. + 지원되는 쿠버네티스 버전을 사용하고 있는지 확인한다. + 퍼즈 인프라 컨테이너를 직접 빌드하려면 + [wincat](https://github.com/kubernetes/kubernetes/tree/master/build/pause/windows/wincat)을 포함시켜야 한다. + +1. 내 윈도우 서버 노드가 프록시 뒤에 있기 때문에 쿠버네티스 설치에 실패한다. + + 프록시 뒤에 있는 경우, 다음 PowerShell 환경 변수를 정의해야 한다. + + ```PowerShell + [Environment]::SetEnvironmentVariable("HTTP_PROXY", "http://proxy.example.com:80/", [EnvironmentVariableTarget]::Machine) + [Environment]::SetEnvironmentVariable("HTTPS_PROXY", "http://proxy.example.com:443/", [EnvironmentVariableTarget]::Machine) + ``` + +### 플란넬 트러블슈팅 + +1. 플란넬(flannel)을 사용하면 클러스터에 다시 조인(join)한 후 노드에 이슈가 발생한다. + + 이전에 삭제된 노드가 클러스터에 다시 조인될 때마다, + flannelD는 새 파드 서브넷을 노드에 할당하려고 한다. + 사용자는 다음 경로에서 이전 파드 서브넷 구성 파일을 제거해야 한다. + + ```powershell + Remove-Item C:\k\SourceVip.json + Remove-Item C:\k\SourceVipRequest.json + ``` + +1. flanneld가 "Waiting for the Network to be created" 상태에서 멈춘다. + + 이 [이슈](https://github.com/coreos/flannel/issues/1066)에 대한 수많은 보고가 있다. + 플란넬 네트워크의 관리 IP가 설정될 때의 타이밍 이슈일 가능성이 높다. + 해결 방법은 start.ps1을 다시 시작하거나 다음과 같이 수동으로 다시 시작하는 것이다. + + ```powershell + [Environment]::SetEnvironmentVariable("NODE_NAME", "") + C:\flannel\flanneld.exe --kubeconfig-file=c:\k\config --iface= --ip-masq=1 --kube-subnet-mgr=1 + ``` + +1. `/run/flannel/subnet.env` 누락으로 인해 윈도우 파드를 시작할 수 없다. + + 이것은 플란넬이 제대로 실행되지 않았음을 나타낸다. + `flanneld.exe`를 다시 시작하거나 + 쿠버네티스 마스터의 `/run/flannel/subnet.env`에서 윈도우 워커 노드의 `C:\run\flannel\subnet.env`로 파일을 수동으로 복사할 수 있고, + `FLANNEL_SUBNET` 행을 다른 숫자로 수정한다. + 예를 들어, 노드 서브넷 10.244.4.1/24가 필요한 경우 다음과 같이 설정한다. + + ```env + FLANNEL_NETWORK=10.244.0.0/16 + FLANNEL_SUBNET=10.244.4.1/24 + FLANNEL_MTU=1500 + FLANNEL_IPMASQ=true + ``` + +### 추가 조사 + +이러한 단계로 문제가 해결되지 않으면, 다음을 통해 쿠버네티스의 윈도우 노드에서 윈도우 컨테이너를 실행하는 데 도움을 받을 수 있다. + +* 스택오버플로우 [윈도우 서버 컨테이너](https://stackoverflow.com/questions/tagged/windows-server-container) 주제 +* 쿠버네티스 공식 포럼 [discuss.kubernetes.io](https://discuss.kubernetes.io/) +* 쿠버네티스 슬랙 [#SIG-Windows Channel](https://kubernetes.slack.com/messages/sig-windows)