|
| 1 | +--- |
| 2 | +title: Guia para Executar Contêineres Windows no Kubernetes |
| 3 | +content_type: tutorial |
| 4 | +weight: 75 |
| 5 | +--- |
| 6 | + |
| 7 | +<!-- visão geral --> |
| 8 | + |
| 9 | +Esta página fornece um passo a passo para executar contêineres Windows usando o Kubernetes. |
| 10 | +Esta página também destaca funcionalidades específicas do Windows dentro do Kubernetes. |
| 11 | + |
| 12 | +É importante notar que criar e implantar serviços e cargas de trabalho no Kubernetes |
| 13 | +comporta-se de forma muito semelhante para contêineres Linux e Windows. |
| 14 | +Os [comandos kubectl](/pt-br/docs/reference/kubectl/) para interagir com o cluster são idênticos. |
| 15 | +Os exemplos nesta página são fornecidos para iniciar sua experiência com contêineres Windows. |
| 16 | + |
| 17 | +<!-- corpo --> |
| 18 | + |
| 19 | +## Objetivos |
| 20 | + |
| 21 | +Configurar um exemplo de implantação para executar contêineres Windows em um nó Windows. |
| 22 | + |
| 23 | +## {{% heading "prerequisites" %}} |
| 24 | + |
| 25 | +Você deve ter acesso a um cluster Kubernetes que inclua um |
| 26 | +nó de trabalho executando Windows Server. |
| 27 | + |
| 28 | +## Começando: Implantando uma Carga de Trabalho Windows |
| 29 | + |
| 30 | +O exemplo de arquivo YAML abaixo implanta um aplicativo simples de servidor web executando dentro de um contêiner Windows. |
| 31 | + |
| 32 | +Crie um manifesto chamado `win-webserver.yaml` com o conteúdo abaixo: |
| 33 | + |
| 34 | +```yaml |
| 35 | +--- |
| 36 | +apiVersion: v1 |
| 37 | +kind: Service |
| 38 | +metadata: |
| 39 | + name: win-webserver |
| 40 | + labels: |
| 41 | + app: win-webserver |
| 42 | +spec: |
| 43 | + ports: |
| 44 | + # a porta em que este serviço deve rodar |
| 45 | + - port: 80 |
| 46 | + targetPort: 80 |
| 47 | + selector: |
| 48 | + app: win-webserver |
| 49 | + type: NodePort |
| 50 | +--- |
| 51 | +apiVersion: apps/v1 |
| 52 | +kind: Deployment |
| 53 | +metadata: |
| 54 | + labels: |
| 55 | + app: win-webserver |
| 56 | + name: win-webserver |
| 57 | +spec: |
| 58 | + replicas: 2 |
| 59 | + selector: |
| 60 | + matchLabels: |
| 61 | + app: win-webserver |
| 62 | + template: |
| 63 | + metadata: |
| 64 | + labels: |
| 65 | + app: win-webserver |
| 66 | + name: win-webserver |
| 67 | + spec: |
| 68 | + containers: |
| 69 | + - name: windowswebserver |
| 70 | + image: mcr.microsoft.com/windows/servercore:ltsc2019 |
| 71 | + command: |
| 72 | + - powershell.exe |
| 73 | + - -command |
| 74 | + - "<# código retirado de https://gist.github.com/19WAS85/5424431# > ; $$listener = New-Object System.Net.HttpListener ; $$listener.Prefixes.Add('http://*:80/') ; $$listener.Start() ; $$callerCounts = @{} ; Write-Host('Listening at http://*:80/') ; while ($$listener.IsListening) { ;$$context = $$listener.GetContext() ;$$requestUrl = $$context.Request.Url ;$$clientIP = $$context.Request.RemoteEndPoint.Address ;$$response = $$context.Response ;Write-Host '' ;Write-Host('> {0}' -f $$requestUrl) ; ;$$count = 1 ;$$k=$$callerCounts.Get_Item($$clientIP) ;if ($$k -ne $$null) { $$count += $$k } ;$$callerCounts.Set_Item($$clientIP, $$count) ;$$ip=(Get-NetAdapter | Get-NetIpAddress); $$header='<html><body><H1>Windows Container Web Server</H1>' ;$$callerCountsString='' ;$$callerCounts.Keys | % { $$callerCountsString+='<p>IP {0} callerCount {1} ' -f $$ip[1].IPAddress,$$callerCounts.Item($$_) } ;$$footer='</body></html>' ;$$content='{0}{1}{2}' -f $$header,$$callerCountsString,$$footer ;Write-Output $$content ;$$buffer = [System.Text.Encoding]::UTF8.GetBytes($$content) ;$$response.ContentLength64 = $$buffer.Length ;$$response.OutputStream.Write($$buffer, 0, $$buffer.Length) ;$$response.Close() ;$$responseStatus = $$response.StatusCode ;Write-Host('< {0}' -f $$responseStatus) } ; " |
| 75 | + nodeSelector: |
| 76 | + kubernetes.io/os: windows |
| 77 | +``` |
| 78 | +
|
| 79 | +{{< note >}} |
| 80 | +Mapeamento de portas também é suportado, mas para simplicidade este exemplo expõe |
| 81 | +a porta 80 do contêiner diretamente para o Service. |
| 82 | +{{< /note >}} |
| 83 | +
|
| 84 | +1. Verifique se todos os nós estão íntegros: |
| 85 | +
|
| 86 | + ```bash |
| 87 | + kubectl get nodes |
| 88 | + ``` |
| 89 | + |
| 90 | +2. Implante o serviço e monitore as atualizações do pod: |
| 91 | + |
| 92 | + ```bash |
| 93 | + kubectl apply -f win-webserver.yaml |
| 94 | + kubectl get pods -o wide -w |
| 95 | + ``` |
| 96 | + |
| 97 | + Quando o serviço for implantado corretamente, ambos os Pods serão marcados como prontos. Para sair do comando de monitoramento, pressione Ctrl+C. |
| 98 | + |
| 99 | +3. Verifique se a implantação foi bem-sucedida. Para verificar: |
| 100 | + |
| 101 | + * Vários pods listados a partir do nó de camada de gerenciamento Linux, use `kubectl get pods` |
| 102 | + * Comunicação de nó para pod através da rede, execute `curl` na porta 80 do IP do seu pod a partir do nó de plano de controle Linux para verificar uma resposta do servidor web |
| 103 | + * Comunicação entre pods, utilize ping entre pods (e através de hosts, se você tiver mais de um nó Windows) usando `kubectl exec` |
| 104 | + * Comunicação de serviço para pod, execute `curl` no IP virtual do serviço (visto em `kubectl get services`) a partir do nó de camada de gerenciamento Linux e de pods individuais |
| 105 | + * Descoberta de serviço, execute `curl` no nome do serviço com o [sufixo DNS padrão do Kubernetes](/docs/concepts/services-networking/dns-pod-service/#services) |
| 106 | + * Conectividade de entrada, execute `curl` no NodePort a partir do nó de plano de controle Linux ou máquinas fora do cluster |
| 107 | + * Conectividade de saída, execute `curl` em IPs externos de dentro do pod usando `kubectl exec` |
| 108 | + |
| 109 | +{{< note >}} |
| 110 | +Os hosts de contêiner Windows não conseguem acessar o IP de serviços alocados neles devido a limitações da pilha de rede do Windows. |
| 111 | +Apenas pods Windows conseguem acessar IPs de serviço. |
| 112 | +{{< /note >}} |
| 113 | + |
| 114 | +## Observabilidade |
| 115 | + |
| 116 | +### Capturando logs de cargas de trabalho |
| 117 | + |
| 118 | +Os logs são um elemento importante da observabilidade; eles permitem que os usuários obtenham insights sobre o aspecto operacional das cargas de trabalho e são um componente essencial na solução de problemas. Como os contêineres Windows e as cargas de trabalho dentro de contêineres Windows se comportam de maneira diferente dos contêineres Linux, os usuários enfrentaram dificuldades na coleta de logs, limitando a visibilidade operacional. |
| 119 | +As cargas de trabalho Windows, por exemplo, geralmente são configuradas para registrar logs no ETW (Event Tracing for Windows) ou enviar entradas para o log de eventos de aplicativos. |
| 120 | +O [LogMonitor](https://github.com/microsoft/windows-container-tools/tree/master/LogMonitor), uma ferramenta de código aberto da Microsoft, é a maneira recomendada para monitorar as fontes de logs configuradas dentro de um contêiner Windows. O LogMonitor oferece suporte para monitorar logs de eventos, provedores ETW e logs personalizados de aplicativos, canalizando-os para o STDOUT para consumo pelo comando `kubectl logs <pod>`. |
| 121 | + |
| 122 | +Siga as instruções na página do GitHub do LogMonitor para copiar seus binários e arquivos de configuração para todos os seus contêineres e adicionar os entrypoints necessários para que o LogMonitor envie seus logs para o STDOUT. |
| 123 | + |
| 124 | + |
| 125 | +## Configurando usuários de contêiner |
| 126 | + |
| 127 | +### Usando nomes de usuário configuráveis para Contêineres |
| 128 | + |
| 129 | +Contêineres Windows podem ser configurados para executar seus entrypoints e processos |
| 130 | +com nomes de usuário diferentes dos padrões da imagem. |
| 131 | +Saiba mais sobre isso [aqui](/pt-br/docs/tasks/configure-pod-container/configure-runasusername/). |
| 132 | + |
| 133 | +### Gerenciando Identidade de Carga de Trabalho com Contas de Serviço Gerenciadas por Grupo |
| 134 | + |
| 135 | +As cargas de trabalho em contêineres Windows podem ser configuradas para usar Contas de Serviço Gerenciadas por Grupo (GMSA). |
| 136 | +As GMSAs são um tipo específico de conta do Active Directory que fornece gerenciamento automático de senhas, |
| 137 | +gerenciamento simplificado de nomes principais de serviço (SPN) e a capacidade de delegar o gerenciamento a outros administradores em vários servidores. |
| 138 | +Contêineres configurados com uma GMSA podem acessar recursos de domínio do Active Directory externo enquanto mantêm a identidade configurada com a GMSA. |
| 139 | +Saiba mais sobre como configurar e usar GMSA para contêineres Windows [aqui](/pt-br/docs/tasks/configure-pod-container/configure-gmsa/). |
| 140 | + |
| 141 | +## Taints e tolerations |
| 142 | + |
| 143 | +Os usuários precisam usar uma combinação de {{<glossary_tooltip text="taint" term_id="taint" >}} e selectors de nós para agendar cargas de trabalho Linux e Windows em seus respectivos nós específicos de sistema operacional. A abordagem recomendada está descrita abaixo, com o objetivo principal de não quebrar a compatibilidade com cargas de trabalho Linux existentes. |
| 144 | + |
| 145 | +Você pode (e deve) definir `.spec.os.name` para cada Pod, para indicar o sistema operacional para o qual os contêineres nesse Pod foram projetados. Para Pods que executam contêineres Linux, defina `.spec.os.name` como `linux`. Para Pods que executam contêineres Windows, defina `.spec.os.name` como `windows`. |
| 146 | + |
| 147 | +{{< note >}} |
| 148 | +Se você estiver executando uma versão do Kubernetes anterior à 1.24, pode ser necessário habilitar o [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) `IdentifyPodOS` para definir um valor para `.spec.pod.os`. |
| 149 | +{{< /note >}} |
| 150 | + |
| 151 | +O escalonador não utiliza o valor de `.spec.os.name` ao atribuir Pods a nós. Você deve usar os mecanismos normais do Kubernetes para [atribuir Pods a nós](/docs/concepts/scheduling-eviction/assign-pod-node/) para garantir que a camada de gerenciamento do seu cluster coloque os Pods em nós que estão executando o sistema operacional apropriado. |
| 152 | + |
| 153 | +O valor de `.spec.os.name` não tem efeito na alocação dos Pods Windows, então taints e tolerations (ou selectors de nós) ainda são necessários para garantir que os Pods Windows sejam atribuídos aos nós Windows apropriados. |
| 154 | + |
| 155 | +### Garantindo que cargas de trabalho específicas de SO sejam atribuídas ao host de contêiner apropriado |
| 156 | + |
| 157 | +Os usuários podem garantir que contêineres Windows sejam agendados no host apropriado usando taints e tolerations. Todos os nós Kubernetes que executam o Kubernetes {{< skew currentVersion >}} têm os seguintes rótulos padrão: |
| 158 | + |
| 159 | +* kubernetes.io/os = [windows|linux] |
| 160 | +* kubernetes.io/arch = [amd64|arm64|...] |
| 161 | + |
| 162 | +Se uma especificação de Pod não especificar um `nodeSelector`, como `"kubernetes.io/os": windows`, é possível que o Pod seja agendado em qualquer host, Windows ou Linux. Isso pode ser problemático, já que um contêiner Windows só pode ser executado em Windows e um contêiner Linux só pode ser executado em Linux. A prática recomendada para o Kubernetes {{< skew currentVersion >}} é usar um `nodeSelector`. |
| 163 | + |
| 164 | +No entanto, em muitos casos, os usuários têm um grande número de implantações existentes para contêineres Linux, bem como um ecossistema de configurações prontas para uso, como chart do Helm da comunidade e casos de geração programática de Pods, como com operadores. Nessas situações, você pode hesitar em fazer a alteração de configuração para adicionar campos `nodeSelector` a todos os Pods e modelos de Pod. A alternativa é usar taints. Como o kubelet pode definir taints durante o registro, ele pode ser facilmente modificado para adicionar automaticamente um taint ao executar apenas em Windows. |
| 165 | + |
| 166 | +Por exemplo: `--register-with-taints='os=windows:NoSchedule'` |
| 167 | + |
| 168 | +Ao adicionar um taint a todos os nós Windows, nada será agendado neles (isso inclui Pods Linux existentes). Para que um Pod Windows seja alocação em um nó Windows, ele precisará tanto do `nodeSelector` quanto da toleration correspondente para escolher Windows. |
| 169 | + |
| 170 | +```yaml |
| 171 | +nodeSelector: |
| 172 | + kubernetes.io/os: windows |
| 173 | + node.kubernetes.io/windows-build: '10.0.17763' |
| 174 | +tolerations: |
| 175 | + - key: "os" |
| 176 | + operator: "Equal" |
| 177 | + value: "windows" |
| 178 | + effect: "NoSchedule" |
| 179 | +``` |
| 180 | + |
| 181 | +### Lidando com várias versões do Windows no mesmo cluster |
| 182 | + |
| 183 | +A versão do Windows Server usada por cada Pod deve corresponder à do nó. Se você quiser usar várias versões do Windows Server no mesmo cluster, deverá definir rótulos adicionais de nó e campos `nodeSelector`. |
| 184 | + |
| 185 | +O Kubernetes adiciona automaticamente um rótulo, [`node.kubernetes.io/windows-build`](/docs/reference/labels-annotations-taints/#nodekubernetesiowindows-build), para simplificar isso. |
| 186 | + |
| 187 | +Este rótulo reflete o número principal, secundário e de build do Windows que precisam corresponder para compatibilidade. Aqui estão os valores usados para cada versão do Windows Server: |
| 188 | + |
| 189 | +| Nome do Produto | Versão | |
| 190 | +|-------------------------------------|-----------------------| |
| 191 | +| Windows Server 2019 | 10.0.17763 | |
| 192 | +| Windows Server 2022 | 10.0.20348 | |
| 193 | + |
| 194 | +### Simplificando com RuntimeClass |
| 195 | + |
| 196 | +[RuntimeClass] pode ser usado para simplificar o processo de usar taints e tolerations. Um administrador de cluster pode criar um objeto `RuntimeClass`, que é usado para encapsular esses taints e tolerations. |
| 197 | + |
| 198 | +1. Salve este arquivo como `runtimeClasses.yml`. Ele inclui o `nodeSelector` apropriado para o SO, arquitetura e versão do Windows. |
| 199 | + |
| 200 | + ```yaml |
| 201 | + --- |
| 202 | + apiVersion: node.k8s.io/v1 |
| 203 | + kind: RuntimeClass |
| 204 | + metadata: |
| 205 | + name: windows-2019 |
| 206 | + handler: example-container-runtime-handler |
| 207 | + scheduling: |
| 208 | + nodeSelector: |
| 209 | + kubernetes.io/os: 'windows' |
| 210 | + kubernetes.io/arch: 'amd64' |
| 211 | + node.kubernetes.io/windows-build: '10.0.17763' |
| 212 | + tolerations: |
| 213 | + - effect: NoSchedule |
| 214 | + key: os |
| 215 | + operator: Equal |
| 216 | + value: "windows" |
| 217 | + ``` |
| 218 | + |
| 219 | +2. Execute `kubectl create -f runtimeClasses.yml` como administrador do cluster. |
| 220 | +3. Adicione `runtimeClassName: windows-2019` conforme apropriado às especificações de Pods. |
| 221 | + |
| 222 | + Por exemplo: |
| 223 | + |
| 224 | + ```yaml |
| 225 | + --- |
| 226 | + apiVersion: apps/v1 |
| 227 | + kind: Deployment |
| 228 | + metadata: |
| 229 | + name: iis-2019 |
| 230 | + labels: |
| 231 | + app: iis-2019 |
| 232 | + spec: |
| 233 | + replicas: 1 |
| 234 | + template: |
| 235 | + metadata: |
| 236 | + name: iis-2019 |
| 237 | + labels: |
| 238 | + app: iis-2019 |
| 239 | + spec: |
| 240 | + runtimeClassName: windows-2019 |
| 241 | + containers: |
| 242 | + - name: iis |
| 243 | + image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019 |
| 244 | + resources: |
| 245 | + limits: |
| 246 | + cpu: 1 |
| 247 | + memory: 800Mi |
| 248 | + requests: |
| 249 | + cpu: .1 |
| 250 | + memory: 300Mi |
| 251 | + ports: |
| 252 | + - containerPort: 80 |
| 253 | + selector: |
| 254 | + matchLabels: |
| 255 | + app: iis-2019 |
| 256 | + --- |
| 257 | + apiVersion: v1 |
| 258 | + kind: Service |
| 259 | + metadata: |
| 260 | + name: iis |
| 261 | + spec: |
| 262 | + type: LoadBalancer |
| 263 | + ports: |
| 264 | + - protocol: TCP |
| 265 | + port: 80 |
| 266 | + selector: |
| 267 | + app: iis-2019 |
| 268 | + ``` |
| 269 | + |
| 270 | +[RuntimeClass]: /docs/concepts/containers/runtime-class/ |
0 commit comments