Kubeadm: Soluções alternativas para o tempo antes de kubeadm HA se tornar disponível

Criado em 16 nov. 2017  ·  74Comentários  ·  Fonte: kubernetes/kubeadm

Os recursos de HA planejados no kubeadm não chegarão à v1.9 (consulte # 261). Então, o que pode ser feito para tornar uma configuração de cluster por kubeadm suficientemente HA?

É assim que se parece agora:

  • Os nós de trabalho podem ser aumentados para obter redundância aceitável.
  • Sem uma configuração ativa / ativa ativa ou pelo menos ativa / passiva do mestre, as falhas do mestre podem causar interrupções significativas.

Portanto, uma configuração principal ativa / ativa ou ativa / passiva precisa ser criada (ou seja, imitar o que o kubeadm supostamente estaria fazendo no futuro):

  1. Substitua o pod etcd local por um cluster etcd de min. _2 x número de mestres_ tamanho. Este cluster pode ser executado no sistema operacional em vez de no K8s.
  2. Configure mais instâncias mestre. Essa é a parte interessante. O guia do Kubernetes para a construção de clusters HA (https://kubernetes.io/docs/admin/high-availability/) pode ajudar a entender o que precisa ser feito. Aqui, gostaria de ter instruções simples passo a passo levando em consideração as particularidades do kubeadm-setup no final.
  3. Não tenho certeza se isso é necessário: Provavelmente configure haproxy / keepalived nos hosts mestre, mova o endereço IP do mestre original mais a terminação SSL para ele.

Isso parece possível se converter a instância mestre existente em um cluster de mestres (2) pode ser feito (o guia do Kubernetes para a construção de clusters HA parece indicar isso). Ativo / ativo não seria mais caro do que ativo / passivo.

Atualmente estou trabalhando nisso. Se eu tiver sucesso, compartilharei o que descobri aqui.

areHA documentatiocontent-gap documentatioimprovement help wanted prioritimportant-soon triaged

Comentários muito úteis

@mbert Tenho seguido seus comentários aqui e só quero que você saiba que segui o guia na documentação e fui capaz de criar um cluster HA k8s funcional usando kubeadm (v1.8.x).

Se você estiver seguindo esta configuração e precisar inicializar o master 2 e 3, poderá reutilizar quase tudo desde o primeiro master. Em seguida, você precisa corrigir os seguintes arquivos de configuração no mestre 2 e 3 para refletir o host atual: /etc/kubernetes/manifests/kube-apiserver.yaml, /etc/kubernetes/kubelet.conf, / etc / kubernetes / admin. conf e /etc/kubernetes/controller-manager.conf

Com relação ao etcd, se você seguir os documentos deste guia, deverá criar um cluster externo de 3 nós etcd que se estenda pelos nós principais de 3 k8s.

Há também um item 'pegadinha' que ainda NÃO foi abordado nos documentos do guia.
Você pode ver esse problema para obter detalhes: https://github.com/cookeem/kubeadm-ha/issues/6

Eu também fiz algumas perguntas relacionadas ao kubeadm HA neste post: https://github.com/cookeem/kubeadm-ha/issues/7

Eu realmente espero que isso possa me dar algumas idéias sobre isso.

Agradeço antecipadamente pelo seu tempo.

Todos 74 comentários

Veja também https://github.com/cookeem/kubeadm-ha - parece cobrir o que desejo alcançar aqui.

@mbert começamos a implementar os recursos de HA e

Para v1.9, iremos documentar o que você está descrevendo aqui na documentação oficial; como conseguir HA com dependências externas, como configurar um LB

Excelente. Estou vasculhando tudo isso agora. No momento, estou preso no bootstrap do master 2 e 3, em particular como configurar o kubelet e o apiserver (quanto posso reutilizar do master 1?) E etcd (estou pensando em usar um bootstrap etc. em uma máquina separada para descoberta). O guia dos documentos é um pouco conciso quando se trata disso.

@mbert Tenho seguido seus comentários aqui e só quero que você saiba que segui o guia na documentação e fui capaz de criar um cluster HA k8s funcional usando kubeadm (v1.8.x).

Se você estiver seguindo esta configuração e precisar inicializar o master 2 e 3, poderá reutilizar quase tudo desde o primeiro master. Em seguida, você precisa corrigir os seguintes arquivos de configuração no mestre 2 e 3 para refletir o host atual: /etc/kubernetes/manifests/kube-apiserver.yaml, /etc/kubernetes/kubelet.conf, / etc / kubernetes / admin. conf e /etc/kubernetes/controller-manager.conf

Com relação ao etcd, se você seguir os documentos deste guia, deverá criar um cluster externo de 3 nós etcd que se estenda pelos nós principais de 3 k8s.

Há também um item 'pegadinha' que ainda NÃO foi abordado nos documentos do guia.
Você pode ver esse problema para obter detalhes: https://github.com/cookeem/kubeadm-ha/issues/6

Eu também fiz algumas perguntas relacionadas ao kubeadm HA neste post: https://github.com/cookeem/kubeadm-ha/issues/7

Eu realmente espero que isso possa me dar algumas idéias sobre isso.

Agradeço antecipadamente pelo seu tempo.

Isso é ótimo - definitivamente preciso disso, pois tenho certeza de que 99% dos usuários do kubeadm têm uma paranóia incômoda no fundo de suas cabeças sobre ha de seu (s) mestre (s).

@ kcao3 obrigado. Vou analisar tudo isso na próxima segunda-feira. Então, eu entendo que não há problema em usar certificados idênticos em todos os três mestres?

Se sim, suponho que em seguida tentarei trazer o kubelet e o apiserver no mestre 2 e 3 usando a configuração do mestre 1 (com IPs e nomes de host modificados lá, é claro) e, em seguida, inicializarei o cluster etcd colocando um modificou etcd.yaml em / etc / kubernetes / manifests.

Hoje tive problemas porque o etcd em execução no mestre 1 já tinha informações de cluster em seu diretório de dados que eu tive que remover primeiro, mas ainda estava tendo problemas. Acho que algumas boas noites de sono serão úteis.

Assim que estiver funcionando, documentarei todo o processo e o publicarei.

@ srflaxu40 sim, e em particular se você tiver um aplicativo que indiretamente requer apiserver em tempo de execução (aplicativo legado e descoberta de serviço no meu caso), você não pode perder o único mestre a qualquer momento.

Converta o _etcd_ de instância única em um cluster

Consegui substituir a única instância _etcd_ por um cluster em um novo cluster K8s. As etapas são aproximadamente estas:

  1. Configure um servidor _etcd_ separado. Esta instância _etcd_ é necessária apenas para inicializar o cluster. Gere um URL de descoberta para 3 nós nele (consulte https://coreos.com/etcd/docs/latest/op-guide/clustering.html#etcd-discovery).
  2. Copie _ / etc / kubernetes_ do mestre 1 para os mestres 2 e 3. Substitua o nome do host e o IP em _ / etc / kubernetes /*.*_ e _ / etc / kubernetes / manifests /*.*_
  3. Crie substituições para _ / etc / kubernetes / manifests / etcd.yaml_ para todos os três mestres: defina todos os URLs de anúncio para os respectivos IPs primários dos hosts, todos os URLs de escuta para 0.0.0.0, adicione o URL de descoberta da etapa 1. Usei o anexado arquivo de modelo Jinja2 etcd.yaml.j2.txt juntamente com _ansible._
  4. Copie as substituições _etcd.yaml_ para _ / etc / kubernetes / manifests_ em todos os três nós mestres.
  5. Agora as coisas tornam-se críticas com o tempo. Espere que o processo _etcd_ local termine, então mova _ / var / lib / etcd / member / wal_ para outro lugar antes que o novo processo apareça (caso contrário, ele ignorará a URL de descoberta).
  6. Quando o novo _etcd_ surgir, ele agora aguardará que as duas instâncias restantes se unam. Portanto, inicie rapidamente o _kubelet_ nos outros dois nós mestres.
  7. Siga os logs do contêiner _etcd_ no primeiro mestre para ver se algo deu errado. Se tudo estiver bem, depois de alguns minutos, o cluster estará operacional novamente.

A etapa 5 é um pouco estranha e descobri que se eu perder o momento certo aqui ou precisar de muito tempo para fazer com que os outros dois mestres se juntem (etapa 6), meu cluster entra em um estado do qual dificilmente pode
recuperar. Quando isso aconteceu, a solução mais simples que encontrei foi desligar _kubelet_ no mestre 2 e 3, executar _kubeadm reset_ em todos os mestres e minions, limpar os diretórios _ / var / lib / etcd_ em todos os mestres e configurar um novo cluster usando _kubeadm iniciar_.

Enquanto isso funciona, eu estaria interessado em possíveis melhorias: Existe alguma abordagem alternativa, mais elegante e robusta para isso (desde que eu ainda queira seguir a abordagem de execução de _etcd_ em contêineres nos mestres)?

Este comentário visa coletar feedback e dicas em um estágio inicial. Vou postar atualizações sobre as próximas etapas de maneira semelhante antes de finalmente documentar isso como um guia que pode ser seguido.

@mbert Por que você não usa um cluster ETCD independente em vez de criar no k8s?

@KeithTt Obrigado por seus comentários. Eu estava pensando sobre isso aqui:

  1. Não usar nenhum dado.
  2. Fique o mais próximo possível da configuração do kubeadm.
  3. Faça com que seja supervisionado por K8s e integrado em qualquer monitoramento que configurei para o meu sistema.
  4. Mantenha o número de serviços em execução no sistema operacional baixo.
  5. Não tornaria as coisas mais fáceis, pois eu ainda teria que lidar com (4) acima.

Se as vantagens de um cluster etcd independente superarem a lista acima, ficarei feliz em ser convencido do contrário.

@mbert Por favor, certifique-se de sincronizar com @jamiehannaford neste esforço, ele também está trabalhando nisso / está empenhado em tornar esses documentos uma coisa na v1.9

@mbert você está disponível para participar de nossa reunião SIG hoje, 9PT ou da implementação de kubeadm, amanhã, 9PT? Adoraria discutir isso com você em uma chamada: +1:

@luxas, na verdade, foi @jamiehannaford quem me pediu para abrir esta edição. Assim que tiver tudo funcionando e documentado, espero receber muitos comentários dele.
9PT, isso é em uma hora, certo? Isso seria bom. Deixe-me saber como entrar em contato com você.

Seguindo guias aqui e ali eu consigo fazer aqui estão meus passos finais

/ cc @craigtracey

@mbert

Criado - não convertido - cluster de 3 nós principais usando kubeadm com cluster de 3 nós etcd implantado em kubernetes

Aqui está o que eu precisava fazer:

  1. Crie 3 cluster de nós mestre usando kubeadm em servidores barebone
  2. Implante o cluster etcd em 3 nós mestres usando kubeadm
  3. Usar pod-network cidr / 27 não padrão

Problemas:

  1. Usar cidr de pod-network não padrão é impossível de configurar usando _kubeadm init_
  2. Não existe documentação sobre a criação de cluster multimestre em barebone. Outros documentos não são tão detalhados quanto poderiam ser

A maneira como fiz isso foi usando as etapas da fase alfa do kubeadm, uma lista resumida a seguir:

em todos os nós mestres:

  1. Iniciar docker - não kubelet

no masternode1:

  1. Criar certificados de CA
  2. Crie certificados apiserver com _-- apiserver-advertise-address_, _-- service-cidr_, _-- apiserver-cert-extra-sans_ parâmetros usados. Aqui, realmente apenas _ --apiserver-cert-extra-sans _ é obrigatório.
  3. Crie o restante dos certificados necessários
  4. Criar configurações de kubeconfig e controlplane
  5. Edite os arquivos yaml recém-criados no diretório / etc / kubernetes / manifest para adicionar quaisquer opções extras necessárias.
    Para mim, é aqui que defino o CIDR da rede pod não padrão de / 27 em kube-control-manager.yaml. Além disso, remova NodeRestriction de --admission-control
  6. Copie o arquivo yaml preparado anteriormente para o cluster etd no diretório / etc / kubernetes / manifest
  7. Copie o diretório / etc / kubernetes para o restante dos nós mestres e edite todos os arquivos necessários para configurá-los para masternode2 e masternode3.
  8. Depois que todos os arquivos forem reconfigurados, inicie o kubelet EM TODOS OS 3 NÓS MESTRES.
  9. Assim que todos os nós estiverem ativados, manchar todos os nós-mestres
  10. Bootstrap todos os tokens
  11. Criar token para ingressar em nós de trabalho
  12. Edite o masterConfig.yaml criado anteriormente e atualize o parâmetro do token
  13. Faça upload de masterConfig para kubernetes
  14. Instalar complementos
  15. Gere --discovery-token-ca-cert-hash e adicione nós de trabalho

Esta é realmente uma pequena lista do que fiz e pode ser automatizada e reproduzida em 5 minutos. Além disso, para mim, o maior bônus foi poder definir CIDR de pod-network não padrão, pois tinha aquela restrição de não ser capaz de poupar o intervalo de endereços IP de classe B.

Se você estiver interessado em uma versão mais detalhada, por favor me avise e tentarei criar alguns documentos sobre como isso foi feito.

@dimitrijezivkovic obrigado pelo seu comentário. Acho que faria sentido reunir todas as informações relevantes para que uma parte da documentação fosse lançada.

Pretendo criar um documento do Google Docs e começar a documentar o que fiz (o que é bastante básico). Então, eu convidaria outras pessoas para participar e escrever extensões, correções, comentários?

Eu agora "documentei" uma configuração muito simples na forma de um pequeno projeto ansible: https://github.com/mbert/kubeadm2ha

É claro que ainda está em andamento, mas já permite configurar um cluster multi-master sem sinos e apitos. Tentei mantê-lo o mais simples possível para que, ao ler, possamos descobrir facilmente o que precisa ser feito e em que ordem.

Amanhã vou começar a escrever isso como uma receita culinária simples em um documento do Google Docs e convidar outras pessoas para colaborar.

Apenas para chamar de forma explícita, há um monte de questões ortogonais misturadas na conversa / sugestões acima. Pode ser útil separá-los separadamente e talvez priorizar alguns acima de outros:

  • durabilidade de dados etcd (multi etcd. Requer 2+ nós etcd)
  • Disponibilidade de dados etcd (multi etcd + redundância. Requer mais de 3 nós etcd)
  • Disponibilidade de apiserver (multi apiserver. Requer um loadbalancer / VIP ou (pelo menos) DNS com vários registros A)
  • Disponibilidade de cm / agendador (multi cm / agendador. Requer 2+ nós mestres e réplicas = 2+ nestes trabalhos)
  • recuperação de reinicialização de todos os mestres (um desafio para auto-hospedado - requer alguma forma de pods persistentes para plano de controle)
  • kubeadm upgrade suporte para multi-apiserver / cm-scheduler (varia dependendo de auto-hospedado versus não auto-hospedado)

Imo, o mínimo de que precisamos é a durabilidade do etcd (ou talvez disponibilidade), e o resto pode esperar. Isso remove o fator de "medo", embora ainda exija alguma intervenção manual para se recuperar de uma falha do mestre primário (ou seja: uma configuração ativa / passiva de algum tipo).

Acho que os detalhes do resto dependem enormemente de auto-hospedado versus "legado", então acho que seria muito simplificado se decidíssemos agora assumir auto-hospedagem (ou não?) - ou claramente bifurcamos as soluções alternativas / documentos nesses dois baldes para não confundir os leitores cortando e alterando.

À parte: um dos desafios aqui é que quase tudo a ver com instalação + atualização muda se você assumir uma configuração auto-hospedada + HA (na maioria das vezes _simplifica_ tudo porque você pode usar atualizações contínuas e maquinário k8s embutido). Eu sinto que, adiando continuamente esta configuração, nós realmente tornamos isso _duro_ para nós mesmos alcançarmos esse objetivo final, e eu me preocupo que vamos continuar empurrando a configuração "real" para trás enquanto trabalhamos no aperfeiçoamento de um único irrelevante- atualizações principais :( Prefiro que abordemos a configuração de HA _primeiro_ e, em seguida, trabalhemos _backwards_ para tentar produzir uma aproximação de host único, se necessário (talvez empacotando trabalhos duplicados temporariamente no host único), em vez de tentar resolver um host único e _então_ de alguma forma acho que essa experiência nos ajudará com vários hosts.

@mbert Eu alcancei a proposta de HA gerando os certs manualmente para cada nó, e sem excluir NodeRestriction , eu uso haproxy+keepalived como balanceador de carga agora, talvez lvs+keepalived seja melhor, Vou documentar os detalhes neste fim de semana, espero compartilhar com você.

image

Para sua informação, @mbert começou a trabalhar em um ótimo guia WIP para kubeadm HA manualmente que adicionaremos aos documentos kubeadm v1.9 eventualmente: https://docs.google.com/document/d/1rEMFuHo3rBJfFapKBInjCqm2d7xGkXzh0FpFO0cRuqg/edit

Por favor, dê uma olhada no documento a todos e forneça seus comentários. Em breve, converteremos isso em markdown e enviaremos como um PR para o kubernetes / site.

Obrigado @mbert e todos os outros que estão ativos no tópico, será uma ótima colaboração!

@mbert / @luxas : esse documento não permite comentários (pelo menos para mim: choro :)

Pronto, usei a configuração errada no documento.

@mbert , tenho uma pergunta para você. Seguindo sua abordagem, supondo que eu tenha um cluster HA k8s funcionando. Você sabe como adicionar novos mestres k8s ao meu cluster existente? O problema que estou enfrentando agora são os certificados que foram gerados com base no número FIXED de hosts mestres k8s no momento em que o cluster foi inicializado. Isso agora impede que qualquer novo mestre se junte ao cluster. No log do kubelet do novo mestre, você veria algo assim: "... x509: o certificado é válido para 192.168.1.x, 192.168.1.y, 192.168.1.z não 192.168.1.n. " (onde .x, .y, .z são o endereço IP dos mestres atuais e .n é o endereço do novo mestre). Você sabe como resolver esse problema? Os nós mestres devem usar os mesmos certificados neste caso?

@ kcao3 Não estou muito familiarizado com este aspecto em particular. Talvez @jamiehannaford possa lhe contar mais sobre isso?

@ kcao3 Cada junção mestre gerará ativos TLS usando o IPv4 específico para esse servidor. A configuração também aceita SANs adicionais, que devem incluir o LB IPv4 que fica na frente dos mestres. Tenho um guia de HA em revisão , então verifique-o se tiver tempo.

Acabei de enviar um novo commit para https://github.com/mbert/kubeadm2ha

  • a rede de flanela agora é suportada (e padrão)
  • há uma instalação básica para o painel (rede NodePort, insegura, ou seja, sem SSL) como um manual separado
  • limpeza de código

@mbert Acabei de ler o guia HA de @jamiehannaford : https://github.com/jamiehannaford/kubernetes.github.io/blob/3663090ea9b9a29a00c79dd2916e11737ccf1802/docs/setup/independent/high-availability.md. É possível em cada nó mestre, podemos fazer com que o kubeadm gere e assine certificados separados usando o mesmo CA.crt e CA.key?

Portanto, as únicas coisas que precisam ser copiadas do mestre primário para os mestres secundários são CA.crt e CA.key. Com essa abordagem, em cada mestre (incluindo primário e secundário), executaremos 'kubeadm init' usando um arquivo de configuração kubeadm gerado com base em um modelo como o seguinte:

apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
kubernetesVersion: v{{ KUBERNETES_VERSION }}
networking:
  podSubnet: {{ POD_NETWORK_CIDR }}
api:
  advertiseAddress: {{ MASTER_VIP }}
apiServerCertSANs:
- {{ MASTER_VIP }}
etcd:
  endpoints:
{% for host in groups['masters'] %}
  - http://{{ hostvars[host]['ansible_default_ipv4']['address'] }}:2379
{% endfor %}

Se essa abordagem funcionar, permitirá que os administradores do k8s adicionem qualquer novo mestre ao cluster multimaters existente no futuro.

Alguma ideia?

@ kcao3 É isso que estou tentando fazer. Eu descobri que também preciso pré-gerar chaves cert + CA proxy, que são diferentes.
Mas agora, quando executo kubeadm init em meus masters, todos os componentes surgem corretamente, mas o kube-proxy ainda falha devido a problemas de autenticação, embora o front-proxy-client.crt agora esteja assinado pelo mesmo CA em todos os nós.

@discordianfish Eu também tive problemas de autenticação, mas ao implantar o Flannel. Gostaria de saber se está relacionado com o que você está vendo.

Nesse ínterim, descobri que o 'proxy CA' (frontend-proxy- *) não está relacionado ao kube-proxy. Ainda tentando descobrir o que está acontecendo, parece que não existe um papel system:node-proxier mas não sei o que é suposto para criá-lo.

Já que as coisas do proxy de front-end eram uma pista falsa, estou começando do zero agora. Mas seria ótimo se alguém pudesse confirmar que deve funcionar para criar as credenciais de CA e apenas executar init em todos os mestres? Dados os endpoints de advertiseAddress, SANs e etcd corretos, é claro?
Porque estou mais preocupado que o kubeadm ainda gere segredos locais que outros mestres não conhecem.

Quando meus mestres aparecem, o kube-proxy está funcionando primeiro, mas o kube-proxy no último mestre falha. Quando recriei os pods, todos falharam. Portanto, ao executar kubeadm init novamente o mesmo etcd várias vezes de hosts diferentes, de alguma forma, a autenticação é interrompida.

A conta de serviço parece correta e tem um segredo:

$ kubectl -n kube-system get ds kube-proxy -o yaml|grep serviceAccount
      serviceAccount: kube-proxy
      serviceAccountName: kube-proxy

$ kubectl -n kube-system get sa kube-proxy -o yaml|grep -A1 secrets
secrets:
- name: kube-proxy-token-5ll9k

$ kubectl -n kube-system get secret kube-proxy-token-5ll9k
NAME                     TYPE                                  DATA      AGE
kube-proxy-token-5ll9k   kubernetes.io/service-account-token   3         16m

Esta conta de serviço também está vinculada a uma função:

$ kubectl get clusterrolebindings kubeadm:node-proxier -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  creationTimestamp: 2017-12-07T12:52:54Z
  name: kubeadm:node-proxier
  resourceVersion: "181"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/kubeadm%3Anode-proxier
  uid: 8a9638df-db4d-11e7-8d7e-0e580b140468
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:node-proxier
subjects:
- kind: ServiceAccount
  name: kube-proxy
  namespace: kube-system

E a função existe e parece boa:

$ kubectl get clusterrole system:node-proxier -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: 2017-12-07T12:52:51Z
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:node-proxier
  resourceVersion: "63"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/system%3Anode-proxier
  uid: 88dfc662-db4d-11e7-8d7e-0e580b140468
rules:
- apiGroups:
  - ""
  resources:
  - endpoints
  - services
  verbs:
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
  - update

Portanto, não tenho certeza do que está acontecendo. Pelo que entendi de tudo, isso deve funcionar assim, mas o apiserver continua registrando: E1207 13:18:20.697707 1 authentication.go:64] Unable to authenticate the request due to an error: [invalid bearer token, [invalid bearer token, crypto/rsa: verification error]]

Ok, então parece que o token é aceito apenas por uma instância dos meus apiservers, provavelmente no mestre onde kubeadm init foi executado pela última vez. Pensei que os tokens da conta de serviço fossem armazenados no etcd.

Mistério resolvido graças a gintas e foxie em # kubernetes-users: Também precisamos pré-gerar as chaves sa e distribuí-las junto com o CA.

Eu segui o guia HA de @jamiehannaford bem de perto e finalmente cheguei a um cluster HA funcional (configurado em uma configuração Vagrant com um balanceador de carga HAProxy na frente de três nós mestres), mas encontrei alguns obstáculos ao longo do caminho e pensei em compartilhe-os aqui, uma vez que provavelmente são relevantes, independentemente da abordagem:

  • É importante que a versão do etcd seja compatível com a versão do Kubernetes que você está executando. Pelo que pude perceber, o guia visa k8s 1.9 e, portanto, usa etcd v3.1.10 . Para uma instalação k8s 1.8 (que eu estava almejando), você deve usar v3.0.17 (usar v3.1.17 fez kubeadm engasgar, não conseguindo extrair a versão do etcd )

  • Tive que executar o etcd usando o systemd, já que executá-lo como pods estáticos em /etc/kubernetes/manifests faria com que as verificações de comprovação de kubeadm falhassem (ele espera que o diretório esteja vazio).

  • Antes de executar kubeadm init em master1 e master2, você precisa esperar que master0 gere certificados e, além de /etc/kubernetes/pki/ca.{crt,key} , copie os arquivos /etc/kubernetes/pki/sa.key e /etc/kubernetes/pki/sa.pub para master1 e master2 (conforme sugerido por @discordianfish). Caso contrário, master1 e master2 gerarão seus próprios certificados de assinatura de tokens de conta de serviço, o que, no meu caso, fez com que o kube-proxy nesses hosts falhassem na autenticação no apiserver.

    Existem também os arquivos front-proxy-ca.{crt,key} e front-proxy-client.{crt,key} que eu não copiei. Não tenho certeza se eles deveriam ter sido copiados do master0 também, mas as coisas parecem estar funcionando de qualquer maneira.

  • O guia de instalação "normal" do --cgroup-driver=systemd para o kubelet por meio de KUBELET_EXTRA_ARGS .

@petergardfjall Ha, é engraçado ver como você se https://github.com/kubernetes/kubeadm/issues/590 , você encontrou uma boa solução para isso?
Não foi necessário usar uma versão especial do etcd. Acho que estou apenas usando os padrões no etcd-wrapper estável do coreos.
Em relação ao front-proxy, francamente não tenho ideia do que seja.

@discordianfish : Não

api:
  advertiseAddress: <apiserver-loadbalancer-ip>

e parece ter sido captado pelo mapa de configuração kube-proxy .

> kubectl get cm -n kube-system kube-proxy -o yaml
apiVersion: v1
data:
  kubeconfig.conf: |
    apiVersion: v1
    kind: Config
    clusters:
    - cluster:
        certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
        server: https://<apiserver-loadbalancer-ip>:6443
      name: default

Ah ok. Certo, ele funciona com um IP do balanceador de carga, mas você não obtém um IP estável ao executar no AWS e usar um ELB, então precisa usar um nome.

@discordianfish eu vejo, isso pode realmente se tornar um problema, já que estou planejando executá-lo na AWS mais tarde. Como você contornou isso?

@jamiehannaford no guia HA, você faz referências ao uso de balanceadores de carga nativos da nuvem. Você experimentou isso? Você conseguiu contornar o número 590?

Não, ainda não encontrei uma solução. No momento, é apenas uma observação em meus documentos para editar este mapa de configuração manualmente.

E eu acabei de atirar no meu pé com o seguinte: kubeadm init em um novo master irá sobrescrever o configmap e https://github.com/kubernetes/kubernetes/issues/57109 torna ainda mais difícil perceber isso.

Portanto, pelo que posso dizer, não há como usar o kubeadm agora em uma configuração multimestre, sem voltar a executar alpha phases manualmente.

O guia HA de @jamiehannaford em geral não

Olá

Acabei de experimentar um pouco com isso e acho que tenho uma configuração de trabalho agora.
Então aqui está o que eu fiz:

O experimento foi realizado em DigtialOcean com 4x 20 $ gotículas (3 mestre + 1 trabalhador)

Primeiro criei 3 gotículas (CoreOS estável):

master1: 188.166.76.108
master2: 188.166.29.53
master3: 188.166.76.133

Em seguida, coloco o seguinte script em cada nó para configurar as peças necessárias para usar o kubeadm com CoreOS:

#!/bin/bash
set -o nounset -o errexit

RELEASE="$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)"
CNI_VERSION="v0.6.0"

mkdir -p /opt/bin
cd /opt/bin
curl -L --remote-name-all https://storage.googleapis.com/kubernetes-release/release/${RELEASE}/bin/linux/amd64/{kubeadm,kubelet,kubectl}
chmod +x {kubeadm,kubelet,kubectl}

mkdir -p /opt/cni/bin
curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-amd64-${CNI_VERSION}.tgz" | tar -C /opt/cni/bin -xz

BRANCH="release-$(cut -f1-2 -d .<<< "${RELEASE##v}")"
cd "/etc/systemd/system/"
curl -L "https://raw.githubusercontent.com/kubernetes/kubernetes/${BRANCH}/build/debs/kubelet.service" | sed 's:/usr/bin:/opt/bin:g' > kubelet.service
mkdir -p "/etc/systemd/system/kubelet.service.d"
cd "/etc/systemd/system/kubelet.service.d"
curl -L "https://raw.githubusercontent.com/kubernetes/kubernetes/${BRANCH}/build/debs/10-kubeadm.conf" | sed 's:/usr/bin:/opt/bin:g' > 10-kubeadm.conf

Crie o mestre inicial:

core@master-01 ~ $ sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-cert-extra-sans="127.0.0.1,188.166.76.108,188.166.29.53,188.166.76.133"
[...]
  kubeadm join --token b11224.fada30ef8a7cbd38 188.166.76.108:6443 --discovery-token-ca-cert-hash sha256:19d34ff6e69203a799ab5984a212684b3dcd446ca5e9d6f6c1a8ae422583b62a
[...]
core@master-01 ~ $ sudo kubectl --kubeconfig=/etc/kubernetes/admin.conf apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml
core@master-01 ~ $ sudo systemctl enable kubelet docker

Em seguida, precisamos criar um cluster etcd, portanto, altere o manifesto do etcd para que o etcd ouça os pares em todas as interfaces ( AVISO : isso não é seguro; na produção, você deve pelo menos usar TLS para autenticação / comunicação de pares)

core@master-01 ~ $ sudo vi /etc/kubernetes/manifests/etcd.yaml
# add --listen-peer-urls=http://0.0.0.0:2380 as a command arg
core@master-01 ~ $ sudo systemctl restart kubelet # for some reason, kubelet does not pick up the change

Altere o peer-url do membro etcd padrão para ipv4 público:

core@master-01 ~ $ ETCDCTL_API=3 etcdctl member list
8e9e05c52164694d, started, default, http://localhost:2380, http://127.0.0.1:2379

core@master-01 ~ $ ETCDCTL_API=3 etcdctl member update 8e9e05c52164694d --peer-urls="http://188.166.76.108:2380"

Agora copie todos os arquivos kubernetes (manifestos / pki) para os outros nós mestres:

$ eval $(ssh-agent)
$ ssh-add <path to ssh key>
$ ssh -A [email protected] # master-02
core@master-02 ~ $ sudo -E rsync -aP --rsync-path="sudo rsync" [email protected]:/etc/kubernetes/ /etc/kubernetes
$ ssh -A [email protected] # master-03
core@master-03 ~ $ sudo -E rsync -aP --rsync-path="sudo rsync" [email protected]:/etc/kubernetes/ /etc/kubernetes

Adicione master-02 ao cluster etcd:

core@master-01 ~ $ ETCDCTL_API=3 etcdctl member add member-02 --peer-urls="http://188.166.29.53:2380"
Member  b52af82cbbc8f30 added to cluster cdf818194e3a8c32

ETCD_NAME="member-02"
ETCD_INITIAL_CLUSTER="member-02=http://188.166.29.53:2380,default=http://188.166.76.108:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"

$ ssh [email protected] # master-02
core@master-02 ~ $ sudo vi /etc/kubernetes/manifests/etcd.yaml
# Add the following as args:
--name=member-02
--initial-cluster=member-02=http://188.166.29.53:2380,default=http://188.166.76.108:2380
--initial-cluster-state=existing
core@master-02 ~ $ sudo systemctl restart kubelet

Adicione master-03 ao cluster etcd:

core@master-01 ~ $ ETCDCTL_API=3 etcdctl member add master-03 --peer-urls="http://188.166.76.133:2380"
Member 874cba873a1f1e81 added to cluster cdf818194e3a8c32

ETCD_NAME="master-03"
ETCD_INITIAL_CLUSTER="member-02=http://188.166.29.53:2380,master-03=http://188.166.76.133:2380,default=http://188.166.76.108:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"

$ ssh [email protected] # master-03
core@master-03 ~ $ sudo vi /etc/kubernetes/manifests/etcd.yaml
# Add the following as args:
--name=master-03
--initial-cluster=member-02=http://188.166.29.53:2380,master-03=http://188.166.76.133:2380,default=http://188.166.76.108:2380
--initial-cluster-state=existing
core@master-03 ~ $ sudo systemctl start kubelet

Portanto, agora devemos ter um cluster etcd de 3 nós.

Agora vamos master-02 e master-03 juntarem-se ao cluster k8s:

$ ssh [email protected] # master-02
core@master-02 ~ $ sudo rm /etc/kubernetes/pki/ca.crt /etc/kubernetes/kubelet.conf
core@master-02 ~ $ sudo kubeadm join --token b11224.fada30ef8a7cbd38 188.166.76.108:6443 --discovery-token-ca-cert-hash sha256:19d34ff6e69203a799ab5984a212684b3dcd446ca5e9d6f6c1a8ae422583b62a
$ ssh [email protected] # master-03
core@master-03 ~ $ sudo rm /etc/kubernetes/pki/ca.crt /etc/kubernetes/kubelet.conf
core@master-03 ~ $ sudo kubeadm join --token b11224.fada30ef8a7cbd38 188.166.76.108:6443 --discovery-token-ca-cert-hash sha256:19d34ff6e69203a799ab5984a212684b3dcd446ca5e9d6f6c1a8ae422583b62a

Marque-os como mestres:

core@master-01 ~ $ sudo kubeadm alpha phase mark-master --node-name master-02
core@master-01 ~ $ sudo kubeadm alpha phase mark-master --node-name master-03

Altere kubelet, kube-scheduler e kube-controller-manager para usar o apiserver local em vez de master-01 apiserver:

core@master-01 ~ $ sudo sed 's/188.166.76.108/127.0.0.1/g' -i /etc/kubernetes/{scheduler.conf,kubelet.conf,controller-manager.conf}
core@master-02 ~ $ sudo sed 's/188.166.76.108/127.0.0.1/g' -i /etc/kubernetes/{scheduler.conf,kubelet.conf,controller-manager.conf}
core@master-03 ~ $ sudo sed 's/188.166.76.108/127.0.0.1/g' -i /etc/kubernetes/{scheduler.conf,kubelet.conf,controller-manager.conf}

Altere o arquivo yaml kube-apiserver para anunciar o ip correto e o ip de verificação de integridade:

core@master-02 ~ $ sudo sed 's/188.166.76.108/188.166.29.53/g' -i /etc/kubernetes/manifests/kube-apiserver.yaml
core@master-03 ~ $ sudo sed 's/188.166.76.108/188.166.76.133/g' -i /etc/kubernetes/manifests/kube-apiserver.yaml

Ative o kubelet, docker e reinicialize:

core@master-01 ~ $ sudo systemctl enable kubelet docker; sudo reboot
core@master-02 ~ $ sudo systemctl enable kubelet docker; sudo reboot
core@master-03 ~ $ sudo systemctl enable kubelet docker; sudo reboot

Altere o kube-proxy para usar o apiserver no localhost:

core@master-01 ~ $ sudo kubectl --kubeconfig=/etc/kubernetes/admin.conf -n kube-system edit configmap kube-proxy
# Change server: https://<ip>:6443 to https://127.0.0.1:6443

Agora, vamos tentar adicionar um nó de trabalho (execute o script na parte superior):
trabalhador-01: 178.62.216.244

$ ssh [email protected]
core@worker-01 ~ $ sudo iptables -t nat -I OUTPUT -p tcp -o lo --dport 6443 -j DNAT --to 188.166.76.108
core@worker-01 ~ $ sudo iptables -t nat -I POSTROUTING -o eth0 -j SNAT --to-source $(curl -s ipinfo.io | jq -r .ip)
core@worker-01 ~ $ sudo sysctl net.ipv4.conf.eth0.route_localnet=1
core@worker-01 ~ $ sudo kubeadm join --token b11224.fada30ef8a7cbd38 127.0.0.1:6443 --discovery-token-ca-cert-hash sha256:19d34ff6e69203a799ab5984a212684b3dcd446ca5e9d6f6c1a8ae422583b62a
core@worker-01 ~ $ sudo systemctl enable kubelet docker

Agora, só precisamos adicionar um balanceador de carga local ao nó de trabalho e tudo está feito.
Salve o seguinte como /etc/nginx/nginx.conf no nó worker-01:

error_log stderr notice;

worker_processes auto;
events {
    use epoll;
    worker_connections 1024;
}

stream {
    upstream kube_apiserver {
        least_conn;
        server 188.166.76.108:6443 max_fails=3 fail_timeout=30s;
        server 188.166.29.53:6443 max_fails=3 fail_timeout=30s;
        server 188.166.76.133:6443 max_fails=3 fail_timeout=30s;
    }

    server {
        listen 127.0.0.1:6443 reuseport;
        proxy_pass kube_apiserver;
        proxy_timeout 10m;
        proxy_connect_timeout 1s;

    }
}

Crie /etc/kubernetes/manifests

core@worker-01 ~ $ sudo mkdir /etc/kubernetes/manifests

Adicione um manifesto estático nginx-proxy como /etc/kubernetes/manifests/nginx-proxy.yaml :

apiVersion: v1
kind: Pod
metadata:
  name: nginx-proxy
  namespace: kube-system
  labels:
    k8s-app: kube-nginx
spec:
  hostNetwork: true
  containers:
  - name: nginx-proxy
    image: nginx:1.13-alpine
    imagePullPolicy: Always
    resources:
      limits:
        cpu: 200m
        memory: 128M
      requests:
        cpu: 50m
        memory: 32M
    volumeMounts:
    - mountPath: /etc/nginx
      name: etc-nginx
      readOnly: true
  volumes:
  - name: etc-nginx
    hostPath:
      path: /etc/nginx

Reinicialize o nó e as regras temporárias de iptables devem desaparecer, e tudo deve funcionar como esperado.


Uma longa postagem, mas mostra que é viável :)

Editar: Esqueci de mudar o servidor API para o nó de trabalho: sudo sed 's/188.166.76.108/127.0.0.1/g' -i /etc/kubernetes/{bootstrap-kubelet.conf,kubelet.conf}
Edit2: Também deve mudar kubectl --kubeconfig=admin.conf -n kube-public get configmap cluster-info

@klausenbusk Ótimo: tada :! Se você quiser levar / melhorar https://github.com/kubernetes/website/pull/6458 , fique à vontade para enviar um PR com mais detalhes sobre o que você fez para ajudar

@klausenbusk , no master-02 e master-03, não entendo como vocês conseguiram entrar? Já que o diretório / etc / kubernetes não está vazio. Você pode esclarecer se há uma etapa faltando?
Obrigado.

@klausenbusk , no master-02 e master-03, não entendo como vocês conseguiram entrar? Já que o diretório / etc / kubernetes não está vazio. Você pode esclarecer se há uma etapa faltando?

Eu removi sudo rm /etc/kubernetes/pki/ca.crt /etc/kubernetes/kubelet.conf conforme documentado, não foi necessário remover todo o diretório.

Para @discordianfish e outros que desejam executar uma configuração de HA no AWS.

Consegui fazer com que uma configuração de HA funcionasse com o ELB da Amazon (apesar de não ter um único endereço IP estático).

Para fazê-lo funcionar, as seguintes etapas (além do guia HA de @jamiehannaford ) precisam ser executadas:

  • Como o ELB não tem um endereço IP estático, não podemos usá-lo como o endereço de anúncio do apiserver. Em vez disso, permitimos que cada mestre anuncie seu próprio endereço IP privado.

    O lado negativo dessa abordagem parece ser que os apiservers vão "brigar" pelo registro do endpoint, reescrevendo-o de vez em quando (como pode ser visto em kubectl get endpoints ), o que, por sua vez, tem consequências para o kube- proxy, que reescreverá seus iptables sempre que uma alteração for detectada.

    Isso não parece prejudicar a exatidão do Kubernetes, mas acho que pode levar a alguma degradação do desempenho em grandes clusters. Alguma ideia?

    A questão é discutida em mais detalhes aqui .

  • Todos os workers kubelets e kube-proxies precisam acessar os servidores da API por meio dos balanceadores de carga FQDN. Uma vez que kubeadm não nos permite especificar servidores diferentes para kube-proxy e kubelets de trabalho (eles simplesmente usarão o endereço IP do apiserver ao qual eles se conectaram em kubeadm join )
    precisamos cuidar disso nós mesmos.

    • A configuração kube-proxy é armazenada como um configmap, que é sobrescrito toda vez que kubeadm init é executado (uma vez para cada nó mestre). Portanto, para cada kubeadm init , precisamos corrigir o configmap da seguinte maneira:

      kubectl get configmap -n kube-system kube-proxy -o yaml> kube-proxy.cm
      # servidor de sudo sed -i : 6443 # g 'kube-proxy.cm
      kubectl apply -f kube-proxy.cm --force

      reinicie todos os pods kube-proxy para garantir que carreguem o novo configmap

      kubectl delete pod -n kube-system -l k8s-app = kube-proxy

    • Em cada trabalhador, precisamos corrigir a configuração kubelet após a junção, para que o kubelet se conecte por meio do balanceador de carga.

      sudo kubeadm join --config = kubeadm-config.yaml

      /etc/kubernetes/kubelet.conf pode não estar presente imediatamente

      wait_for 60 [-f /etc/kubernetes/kubelet.conf]
      # servidor de sudo sed -i : 6443 # g '/etc/kubernetes/kubelet.conf
      sudo systemctl restart kubelet

Com essa abordagem, parece que tenho um cluster de trabalho em que um mestre por vez pode ficar inativo sem interrupção do serviço (apiserver).

Isso não parece prejudicar a exatidão do Kubernetes, mas acho que pode levar a alguma degradação do desempenho em grandes clusters. Alguma ideia?

Você pode mudar para o novo reconciliador de aluguel no 1.9, ele deve corrigir a "briga" sobre o problema do terminal.

Excelente conselho, @klausenbusk. Funcionou como um encanto.

@petergardfjall

eles simplesmente usarão o endereço IP do apiserver ao qual eles se conectaram em kubeadm join

O que acontece se você fizer kubeadm join com o IP do LB?

Em termos de kubelet, acho que é uma edição manual necessária. Precisa adicionar ao guia HA.

@jamiehannaford O problema ao usar o ELB da Amazon é que ele não fornece um endereço IP único e estável, portanto, não existe um IP LB que eu possa usar (consulte https://stackoverflow.com/a/35317682/7131191 )

Portanto, por enquanto, os workers ingressam por meio do FQDN do ELB, que o encaminha para um dos apiservers, o que, por anunciar seu próprio endereço IP, faz com que o worker configure seu kubelet para usar aquele endereço IP (e não o FQDN do ELB). Portanto, para garantir que o kubelet passe pelo balanceador de carga apiserver, o kubelet.conf precisa ser corrigido posteriormente com o FQDN do ELB e o kubelet reiniciado.

Acabei de abrir o código fonte do HA kubeadm. Vem com algumas advertências e solução alternativa feia (especialmente o hack kube-proxy é feio). Mas funciona: https://github.com/itskoko/kubecfn

Eu fiz alguns trabalhos no guia de configuração de HA no Google Docs :

  • assumiu algumas mudanças propostas nos comentários
  • suporte para plugin de rede 'calico'
  • assumiu a configuração do _etcd_ SSL do documento guia oficial escrito por @jamiehannaford

Essas mudanças foram implementadas em minha automação baseada em

  • configuração automática do operador etcd para aplicativos em execução no cluster (não o próprio cluster)
  • pré-busca de imagens necessárias para a operação do Kubernetes e copiá-las para os hosts de cluster
  • Configuração do painel (inseguro, sem SSL) com a porta 30990 no NodePort (se nenhum LB estiver configurado)

Publiquei o script do instalador HA kubernetes baseado em kubeadm no qual tenho trabalhado recentemente. Esperemos que colocar meus comentários anteriores em contexto e servir como um exemplo concreto de como automatizar os passos de @jamiehannaford 's guia de HA , que segue bem de perto.

É um script python executado em duas fases: render que cria "ativos de cluster" na forma de chaves SSH, certificados e scripts de inicialização, e uma fase install que executa esses scripts de inicialização por SSH.

Os scripts foram testados em um cluster Vagrant local e na AWS. Dois "scripts de provedor de infraestrutura" estão incluídos no repo (vagrant e AWS via Terraform) para provisionar o balanceador de carga de cluster e VMs necessários.

Sinta-se à vontade para experimentar. https://github.com/elastisys/hakube-installer

Ainda não encontrei uma maneira de atualizar um cluster HA instalado usando kubeadm e as etapas manuais descritas no meu guia de configuração HA no google docs .

O que tentei até agora é o seguinte:

  1. Desligue o keepalived nos mestres secundários, execute o upgrade do kubeadm no mestre primário, aplique as mesmas mudanças em / etc / kubernetes / manifestos nos mestres secundários como havia no mestre primário e inicie o keepalived nos mestres secundários.
  2. Igual a (1), mas além de keepalived, também fecha (e depois inicia) o kubelet e o docker nos mestres secundários.
  3. Igual a (2), mas antes de aplicar a atualização no mestre primário, cordon (e depois desacordar) todos os mestres secundários.

Isso não funcionou e o resultado foi praticamente o mesmo em todos os casos. O que obtenho nos registros dos mestres secundários é assim:

Unable to register node "master-2.mylan.local" with API server: nodes "master-2.mylan.local" is forbidden: node "master-1.mylan.local" cannot modify node "master-2.mylan.local"

Failed to update status for pod "kube-apiserver-master-2.mylan.local_kube-system(6d84ab47-0008-11e8-a558-0050568a9775)": pods "kube-apiserver-master-2.mylan.local" is forbidden: node "master-1.mylan.local" can only update pod status for pods with spec.nodeName set to itself

Failed to update status for pod "kube-controller-manager-master-2.mylan.local_kube-system(665da2db-0008-11e8-a558-0050568a9775)": pods "kube-controller-manager-master-2.mylan.local" is forbidden: node "master-1.mylan.local" can only update pod status for pods with spec.nodeName set to itself

Failed to update status for pod "kube-scheduler-master-2.mylan.local_kube-system(65c6a0b3-0008-11e8-a558-0050568a9775)": pods "kube-scheduler-master-2.mylan.local" is forbidden: node "master-1.mylan.local" can only update pod status for pods with spec.nodeName set to itself

Failed to update status for pod "kube-flannel-ds-ch8gq_kube-system(47cccaea-0008-11e8-b5b5-0050568a9e45)": pods "kube-flannel-ds-ch8gq" is forbidden: node "master-1.mylan.local" can only update pod status for pods with spec.nodeName set to itself

Failed to update status for pod "kube-proxy-htzg7_kube-system(47cc9d00-0008-11e8-b5b5-0050568a9e45)": pods "kube-proxy-htzg7" is forbidden: node "master-1.mylan.local" can only update pod status for pods with spec.nodeName set to itself

Deleting mirror pod "kube-controller-manager-master-2.mylan.local_kube-system(665da2db-0008-11e8-a558-0050568a9775)" because it is outdated

Failed deleting a mirror pod "kube-controller-manager-master-2.mylan.local_kube-system": pods "kube-controller-manager-master-2.mylan.local" is forbidden: node "master-1.mylan.local" can only delete pods with spec.nodeName set to itself

Failed creating a mirror pod for "kube-controller-manager-master-2.mylan.local_kube-system(78432ebfe5d8dfbb93f8173decf3447e)": pods "kube-controller-manager-master-2.mylan.local" is forbidden: node "master-1.mylan.local" can only create pods with spec.nodeName set to itself

[... and so forth, repeats itself ...]

Alguém tem uma dica de como proceder para atualizar os mestres secundários de forma limpa?

@mbert Este parece ser um problema de RBAC. Você garantiu que o nome do nó corresponde à substituição do nome do host ?

Além disso, você redefiniu o etcd para cada etapa? Isso provavelmente explica porque você viu o mesmo resultado.

@jamiehannaford Não estou usando nenhuma substituição de nome de host, nem no kubelet nem na configuração de inicialização do kubeadm. E, sim, estou reiniciando o etcd, ou seja, desmontar o cluster, instalar um novo do zero e tentar atualizá-lo.

Vou dar uma chance à configuração de uma substituição de nome de host para kubelet e ver se isso leva a algum outro resultado.

Parece que definir a substituição do nome do host ao configurar o cluster ajuda, ou seja, torna os mestres secundários atualizáveis. Quando isso se tornar um procedimento padronizado, irei documentá-lo no guia de configuração de HA no google docs .

Olá @mbert e outros - Desde o ano passado ou assim, tenho vários clusters k8s (kubeadm e outros) direcionados do Cobbler / Puppet no CoreOS e CentOS. No entanto, nenhum deles foi HA.

Minha próxima tarefa é integrar HA do K8s e quero usar o kubeadm. Não estou certo se a ir com do @mbert guia de configuração HA ou @jamiehannaford 's guia de HA .

Além disso, esta manhã li a proposta de @timothysc para uma configuração de plano de controle altamente disponível para implantações de 'kubeadm'. e eu gosto da abordagem "semente do etcd inicial" que ele descreve. No entanto, não vejo essa mesma abordagem no trabalho de @mbert ou @jamiehannaford . @mbert parece usar um único etcd hospedado por k8s, enquanto o documento de @jamiehannaford documenta a abordagem clássica do etcd externo (que é exatamente o que usei para meus outros esforços não HA POC).

o que vocês recomendam? Etd externo, auto-hospedado único ou localização e uso do etcd "seed" (com pivô para hospedado em k8s)? Se for o último - que guia ou documentação você sugere?

TIA!

@andybrucenet O

@andybrucenet Não exatamente - estou usando um cluster externo etcd como @jamiehannaford propõe em seu guia. Na verdade, as abordagens descritas em nossos respectivos documentos devem ser bastante semelhantes. Baseia-se na configuração do cluster etcd de que você sente que precisa e depois faz com que o kubeadm o use ao inicializar o cluster Kubernetes.

No momento, estou mais ou menos prestes a terminar meu guia e a implementação baseada em ansible documentando e implementando um procedimento de atualização funcional - que (e algumas correções de bugs) deve ser feito na próxima semana.

Não tenho certeza se haverá alguma necessidade de transferir meu guia para o seu, @jamiehannaford , o que você acha?

Na verdade, a substituição do nome do host era desnecessária. Ao executar kubeadm upgrade apply , algumas configurações padrão sobrescrevem minhas adaptações, por exemplo, NodeRestriction é reativado (também meu escalonamento de instâncias do _Kube DNS_ é redefinido, mas é claro que isso não foi um obstáculo aqui). Corrigir a regra de admissão NodeRestriction de _ / etc / kubernetes / manifests / kube-apiserver.yaml_ resolveu o problema.

Agora escrevi um capítulo sobre como atualizar clusters de HA para o meu guia de configuração de HA .

Além disso, adicionei o código para automatizar esse processo ao meu projeto ansible no github . Dê uma olhada no arquivo README.md para obter mais informações.

@mbert para o processo de atualização que você descreveu, quais são os motivos exatos para copiar manualmente as configurações e manifestos de /etc/kubernetes no mestre primário para os mestres secundários em vez de simplesmente executar kubeadm upgrade apply <version> no mestres secundários também?

@mattkelly Pareceu-me bastante perigoso.
Como os mestres do cluster HA usam uma configuração ativa / passiva, mas o kubeadm conhece apenas um mestre, achei arriscado executá-lo novamente em um mestre diferente.
Eu posso estar errado embora.

Respondendo a mim mesmo: depois de consultar o guia de Jamie no kubernetes.io , executar o kubeadm nos mestres pode funcionar, mesmo ao configurar o cluster. Vou tentar fazer isso na próxima semana e provavelmente fazer algumas alterações em meus documentos de acordo.

FWIW, executar kubeadm nos mestres secundários parece ter funcionado muito bem para mim (incluindo a atualização) - mas preciso entender melhor os riscos exatos em cada estágio. Eu tenho acompanhado de guia que é automatizado por @petergardfjall '@jamiehannaford s hakube-installer (sem suporte atualização ainda, porém, assim que eu testei isso manualmente).

Editar: Também é importante notar que estou testando apenas na v1.9 +. A atualização foi de v1.9.0 para v1.9.2.

Eu agora segui o guia sobre kubernetes.io que @jamiehannaford criou, ou seja, executou kubeadm init em todas as máquinas mestres (depois de ter copiado /etc/kubernetes/pki/ca.* para os mestres secundários). Isso funciona muito bem para configurar o cluster. Para poder atualizar para a v1.9.2, estou configurando a v1.8.3 aqui.

Agora estou tendo problemas ao tentar atualizar o cluster: A execução de kubeadm upgrade apply v1.9.2 no primeiro mestre falha:

[controlplane] Wrote Static Pod manifest for component kube-controller-manager to "/etc/kubernetes/tmp/kubeadm-upgraded-manifests872757515/kube-controller-manager.yaml"
[controlplane] Wrote Static Pod manifest for component kube-scheduler to "/etc/kubernetes/tmp/kubeadm-upgraded-manifests872757515/kube-scheduler.yaml"
[upgrade/staticpods] Moved new manifest to "/etc/kubernetes/manifests/kube-apiserver.yaml" and backed up old manifest to "/etc/kubernetes/tmp/kubeadm-backup-manifests647361774/kube-apiserver.yaml"
[upgrade/staticpods] Waiting for the kubelet to restart the component
[upgrade/apply] FATAL: couldn't upgrade control plane. kubeadm has tried to recover everything into the earlier state. Errors faced: [timed out waiting for the condition]

Esta etapa falha reproduzivelmente (eu sempre começo do zero, ou seja, removo todos os arquivos de configuração mais os dados etcd de todos os nós antes de iniciar uma nova configuração).

Tentei várias variações, mas sem sucesso:

  • Faça com que o kubelet use a instância do servidor de API local ou aquela apontada pelo IP virtual
  • fazer com que o kube-proxy use a instância do servidor API local ou aquela apontada pelo IP virtual

Anexei alguns logs. No entanto, não consigo encontrar nenhum padrão comum que explique esse problema para mim. Talvez seja algo que eu simplesmente não sei?

upgrade-failed-proxy-on-vip.log
upgrade-failed-proxy-and-kubelet-on-vip.log
upgrade-failed-proxy-and-kubelet-on-local-ip.log

Depois de experimentar outras coisas, tudo se resume ao seguinte:

  • A atualização do mestre que foi configurado por último (ou seja, aquele em que kubeadm init foi executado por último ao configurar o cluster) funciona.
  • Posso fazer com que os outros nós funcionem também, se editar configmap/kubeadm-config e alterar o valor de MasterConfiguration.nodeName lá para o nome do host do respectivo mestre ou simplesmente excluir essa linha.

Outros, como @mattkelly , foram capazes de realizar a atualização sem editar configmap/kubeadm-config , portanto, a maneira como configuro as coisas deve ser diferente.

Alguém tem idéia do que devo mudar, para que a atualização funcione sem esse truque (bastante sujo)?

Tentei atualizar de 1.8.3 e 1.9.0 para 1.9.2, com o mesmo resultado.

@mbert Agora estou reproduzindo seu problema de um novo cluster v1.9.0 criado com o

Verifiquei que excluir a linha nodeName de configmap/kubeadm-config para cada subseqüente corrige o problema.

Obrigado, isso é muito útil. Agora adicionei o patch configmap/kubeadm-config às minhas instruções.

@mbert oops, descobri a diferença :). Para atualizações anteriores, eu fornecia a configuração gerada durante a configuração por meio de --config (memória muscular, eu acho). É por isso que nunca precisei de uma solução alternativa. Acredito que sua solução alternativa seja mais correta caso o cluster tenha mudado desde o tempo de inicialização. Seria ótimo descobrir como evitar esse hack, mas não é tão ruim enquanto isso - especialmente em comparação com todas as outras soluções alternativas.

Olá,
O kubeadm 1.10 removerá qualquer uma das pré-etapas / soluções alternativas exigidas atualmente para HA no 1.9?
Por exemplo, a criação manual de um bootstrap etcd, geração de chaves etcd, etc?

Fechando este item, pois o documento 1.10 foi lançado e iremos avançar para a história do HA em 1.11

/ cc @fabriziopandini

Esta página foi útil?
0 / 5 - 0 avaliações