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:
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):
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.
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.
Consegui substituir a única instância _etcd_ por um cluster em um novo cluster K8s. As etapas são aproximadamente estas:
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:
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:
Problemas:
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:
no masternode1:
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:
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ê.
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
@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
kubectl apply -f kube-proxy.cm --force
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
wait_for 60 [-f /etc/kubernetes/kubelet.conf]
# servidor de sudo sed -i
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 :
Essas mudanças foram implementadas em minha automação baseada em
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:
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:
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:
kubeadm init
foi executado por último ao configurar o cluster) funciona.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
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.