TL DR
Nós aumentamos o cluster para atender a aplicativos da web sem estado com entrada , permite criptografar , sem usar ferramentas de automação como kubespray, kubeadm e outras.
Tempo de leitura: ~ 45-60 minutos, tempo de reprodução: a partir de 3 horas.
Preâmbulo
Fui solicitado a escrever um artigo pela necessidade de meu próprio cluster Kubernetes para experimentação. As soluções de instalação e configuração automatizadas de código aberto não funcionaram no meu caso, pois usei distribuições Linux não convencionais. O trabalho intensivo com kubernetes no IPONWEB incentiva você a ter essa plataforma, resolvendo suas tarefas de maneira confortável, inclusive para projetos domésticos.
Componentes
Os seguintes componentes aparecerão no artigo:
- Seu Linux favorito - usei o Gentoo (nó-1: systemd / nó-2: openrc), Ubuntu 18.04.1.
- Servidor Kubernetes - kube-apiserver, kube-controller-manager, kube-scheduler, kubelet, kube-proxy.
- Plugins Containerd + CNI (0.7.4) - para organizar a conteinerização, usaremos containererd + CNI em vez de janela de encaixe (embora inicialmente toda a configuração tenha sido carregada na janela de encaixe, nada impede que ela seja usada, se necessário).
- CoreDNS - para organizar a descoberta de serviços de componentes que trabalham dentro do cluster kubernetes. Recomenda-se uma versão não inferior a 1.2.5, pois com esta versão há suporte sensato para que os coredns funcionem como um processo em execução fora do cluster.
- Flanela - para organizar uma pilha de rede, comunicar lares e contêineres entre si.
- Seu db favorito .

Limitações e premissas
- O artigo não examina o custo das soluções vps / vds no mercado, bem como a possibilidade de implantar máquinas nesses serviços. Supõe-se que você já tenha algo expandido ou poderá fazê-lo você mesmo. Além disso, a instalação / configuração do seu banco de dados favorito e repositório do docker privado, se você precisar de um, não é coberta.
- Podemos usar os plugins e a docker containserd + cni. Este artigo não considera o uso do Docker como uma ferramenta de contêiner. Se você quiser usar o docker, poderá configurar a flanela de acordo . Além disso, você precisará configurar o kubelet, ou seja, remover todas as opções relacionadas ao containererd. Como minhas experiências mostraram, a janela de encaixe e o container em diferentes nós como contêineres funcionarão corretamente.
- Não podemos usar
host-gw
back host-gw
end host-gw
para flanela, leia a seção Configuração de flanela para obter mais detalhes - Não usaremos nada para monitorar, fazer backups, salvar arquivos do usuário (status), armazenar arquivos de configuração e código do aplicativo (git / hg / svn / etc)
1. Introdução
No decorrer do trabalho, usei um grande número de fontes, mas quero mencionar separadamente um Kubernetes bastante detalhado, o guia da maneira mais difícil , que cobre cerca de 90% da configuração básica de seu próprio cluster. Se você já leu este manual, pode prosseguir com segurança diretamente para a seção Configuração da flanela .
DesignaçõesLista de Termos / Glossário
- api-server - uma máquina física ou virtual na qual está localizado um conjunto de aplicativos para execução e funcionamento correto do kubernetes kube-apiserver. Para os fins deste artigo, é etcd, kube-apiserver, kube-controller-manager, kube-scheduler.
- master - uma estação de trabalho dedicada ou instalação do VPS, sinônimo de api-server.
- nó X - uma estação de trabalho dedicada ou instalação VPS,
X
indica o número de série da estação. Neste artigo, todos os números são únicos e são essenciais para a compreensão:
- nó-1 - número da máquina 1
- nó-2 - número da máquina 2
- vCPU - CPU virtual, núcleo do processador. O número corresponde ao número de núcleos: 1vCPU - um núcleo, 2vCPU - dois e assim por diante.
- usuário - usuário ou espaço do usuário. Ao usar o
user$
nas instruções da linha de comando, o termo refere-se a qualquer máquina cliente. - worker - o nó de trabalho no qual os cálculos diretos serão executados, como sinônimo de
node-X
- resource é a entidade na qual o cluster Kubernetes opera. Os recursos do Kubernetes incluem um grande número de entidades relacionadas .
Soluções de arquitetura de rede
No processo de aumento do cluster, não defini a tarefa de otimizar os recursos de ferro de forma a caber no orçamento de US $ 20 por mês. Era apenas necessário montar um cluster de trabalho com pelo menos dois nós de trabalho (nós). Portanto, inicialmente o cluster ficou assim:
- máquina com 2 vCPU / 4G RAM: api-server + node-1 [20 $]
- máquina com 2 RAM vCPU / 4G: nó-2 [$ 20]
Depois que a primeira versão do cluster funcionou, decidi reconstruí-lo para distinguir entre os nós responsáveis pela execução de aplicativos no cluster (nós de trabalho, eles também são trabalhadores) e a API do servidor mestre.
Como resultado, recebi a resposta para a pergunta: "Como obter um cluster mais ou menos barato, mas funcional, se eu quiser colocar não os aplicativos mais espessos lá".
Decisão de US $ 20
(Planejado para ser assim)
Informações gerais da arquitetura Kubernetes
(Roubado da Internet se alguém de repente ainda não sabe ou não viu)
Componentes e seu desempenho
A primeira etapa foi entender quantos recursos eu preciso para executar pacotes de software diretamente relacionados ao cluster. A busca por "requisitos de hardware" não deu resultados específicos, então tive que abordar a tarefa de um ponto de vista prático. Como medida de MEM e CPU, tirei estatísticas do systemd - podemos assumir que as medições foram realizadas de maneira muito amadora, mas não tive a tarefa de obter valores precisos, pois ainda não consegui encontrar opções mais baratas do que US $ 5 por instância.
Por que exatamente $ 5?Foi possível encontrar o VPS / VDS mais barato ao hospedar servidores na Rússia ou na CEI, mas as tristes histórias associadas ao ILV e suas ações criam certos riscos e dão origem a um desejo natural de evitá-los.
Então:
- Servidor principal / Configuração do servidor (nós principais):
- etcd (3.2.17): 80 - 100M, as métricas foram obtidas no tempo selecionado aleatoriamente. O consumo médio de memória Etcd não excedeu 300M;
- kube-apiserver (1.12.x - 1.13.0): 237.6M ~ 300M;
- kube-controller-manager (1.12.x - 1.13.0): aproximadamente 90M, não subiu acima de 100M;
- kube-scheduler (1.12.x - 1.13.0): aproximadamente 20M, o consumo acima de 30-50M não é fixo.
- Configuração do servidor de trabalho (nós de trabalho):
- kubelet (1.12.3 - 1.13.1): aproximadamente 35 Mb, o consumo acima de 50M não é fixo;
- kube-proxy (1.12.3 - 1.13.1): aproximadamente 7.5 - 10M;
- flanela (0.10.0): aproximadamente 15-20M;
- coredns (1.3.0): aproximadamente 25M;
- Containerd (1.2.1): O consumo de Containerd é baixo, mas as estatísticas também mostram os processos de contêiner iniciados pelo daemon.
É necessário oerderd / docker nos nós principais?Não, não é necessário . O nó mestre não requer docker ou container em si, embora exista um grande número de manuais na Internet que, para uma finalidade ou outra, incluem o uso do ambiente para contêiner. Na configuração em questão, o containerd foi desativado intencionalmente da lista de dependências, no entanto, não realço vantagens óbvias dessa abordagem.
A configuração fornecida acima é mínima e suficiente para iniciar o cluster. Nenhuma ação / componente adicional é necessária, a menos que você queira adicionar algo como desejar.
Para criar um cluster de teste ou cluster para projetos domésticos, 1vCPU / 1G RAM será suficiente para o nó mestre funcionar. Obviamente, a carga no nó mestre variará dependendo do número de trabalhadores envolvidos, bem como da disponibilidade e do volume de solicitações de terceiros ao servidor da API.
Explodi as configurações de mestre e trabalhador da seguinte maneira:
- 1x Mestre com componentes instalados: etcd, kube-apiserver, kube-controller-manager, kube-scheduler
- 2x Trabalhadores com componentes instalados: container, coredns, flanela, kubelet, kube-proxy
Configuração
Para configurar o assistente, os seguintes componentes são necessários:
etcd - para armazenar dados para api-server, bem como para flanela;
kube-apiserver - na verdade, api-server;
kube-controller-manager - para gerar e processar eventos;
kube-scheduler - para distribuição de recursos registrados através do servidor de API - por exemplo, lareira .
Para a configuração dos cavalos de trabalho, são necessários os seguintes componentes:
kubelet - para executar as lareiras, definir configurações de rede;
kube-proxy - para organizar roteamento / balanceamento de serviços kubernetes;
coredns - para descoberta de serviços dentro de contêineres em execução;
flanela - para organizar o acesso à rede de contêineres operando em diferentes nós, bem como para a distribuição dinâmica de redes entre os nós do cluster (nó kubernetes).
CorednsUma pequena digressão deve ser feita aqui: os coredns também podem ser iniciados no servidor mestre. Não há restrições que forçam os coredns a serem executados nos nós de trabalho, exceto pela nuance de configuração do coredns.service, que simplesmente não inicia em um servidor Ubuntu padrão / não modificado devido a um conflito com o serviço resolvido pelo sistema. Não tentei resolver esse problema, pois os servidores de 2 ns localizados nos nós de trabalho estavam muito felizes comigo.
Para não perder tempo agora se familiarizando com todos os detalhes do processo de configuração de componentes, sugiro que você se familiarize com eles no guia da maneira mais difícil do Kubernetes . Vou me concentrar nos recursos distintivos da minha opção de configuração.
Arquivos
Todos os arquivos para o funcionamento dos componentes do cluster para o assistente e os nós de trabalho são colocados em / var / lib / kubernetes / por conveniência. Se necessário, você pode colocá-los de outra maneira.
Certificações
A base para a geração de certificados ainda é a mesma Kubernetes da maneira mais difícil , praticamente não há diferenças significativas. Para regenerar certificados subordinados, scripts simples de bash foram escritos em torno de aplicativos cfssl - isso foi muito útil no processo de depuração.
Você pode gerar certificados para suas necessidades usando os scripts abaixo, receitas do Kubernetes da maneira mais difícil ou outras ferramentas adequadas.
Geração de certificado usando scripts bashVocê pode obter scripts aqui: bootstrap do kubernetes . Antes de iniciar, edite o arquivo certs / env.sh , especificando suas configurações. Um exemplo:
$ cd certs
Se você usou o env.sh
e especificou corretamente todos os parâmetros, não há necessidade de tocar nos certificados gerados. Se você cometeu algum erro em algum momento, os certificados podem ser regenerados em partes. Os scripts bash acima são triviais, não é difícil classificá-los.
Uma observação importante - você não deve recriar frequentemente os ca.pem
e ca-key.pem
, pois são os certificados raiz de todos os certificados subsequentes; em outras palavras, será necessário recriar todos os certificados anexos e entregá-los a todas as máquinas e todos os diretórios necessários.
O mestre
Os certificados necessários para iniciar os serviços no nó principal devem ser colocados em /var/lib/kubernetes/
:
- kubernetes-key.pem - permanece nos servidores principais.
- service-account.pem - necessário apenas para daemons do kube-controller-manager.
- service-account-key.pem - da mesma forma.
Unidades de Trabalho
- ca.pem - necessário para todos os serviços envolvidos nos nós de trabalho (kubelet, kube-proxy), bem como para flanela, coredns. Entre outras coisas, seu conteúdo é incluído nos arquivos kubeconfig quando são gerados usando o kubectl.
- kubernetes-key.pem - necessário apenas para flanela e coredns se conectarem ao etcd, que está localizado no nó principal da api.
- kubernetes.pem - semelhante ao anterior, necessário apenas para flanela e coredns.
- kubelet / node-1.pem - chave para a autorização node-1.
- kubelet / node-1-key.pem - chave para autorização node-1.
Importante! Se você tiver mais de um nó, cada nó incluirá os arquivos node-X-key.pem
, node-X.pem
e node-X.kubeconfig
dentro do kubelet.
Depuração de certificadoDepuração de certificado
Às vezes, pode ser necessário verificar como o certificado está configurado para descobrir quais hosts IP / DNS foram usados para gerá-lo. O cfssl-certinfo -cert <cert>
nos ajudará com isso. Por exemplo, aprendemos essas informações para o node-1.pem
:
$ cfssl-certinfo -cert node-1.pem
{ "subject": { "common_name": "system:node:node-1", "country": "RU", "organization": "system:nodes", "organizational_unit": "Infrastructure Unit", "locality": "Moscow", "province": "Moscow", "names": [ "RU", "Moscow", "Moscow", "system:nodes", "Infrastructure Unit", "system:node:node-1" ] }, "issuer": { "common_name": "Kubernetes", "country": "RU", "organization": "Kubernetes", "organizational_unit": "Infrastructure", "locality": "Moscow", "province": "Moscow", "names": [ "RU", "Moscow", "Moscow", "Kubernetes", "Infrastructure", "Kubernetes" ] }, "serial_number": "161113741562559533299282037709313751074033027073", "sans": [ "w40k.net", "node-1", "178.79.168.130", "192.168.164.230" ], "not_before": "2019-01-04T14:24:00Z", "not_after": "2029-01-01T14:24:00Z", "sigalg": "SHA256WithRSA", "authority_key_id": "6:C8:94:67:59:55:19:82:AD:ED:6D:50:F1:89:B:8D:46:78:FD:9A", "subject_key_id": "A1:5E:B3:3C:45:14:3D:C6:C:A:97:82:1:D5:2B:75:1A:A6:9D:B0", "pem": "<pem content>" }
Todos os outros certificados para kubelet e kube-proxy são incorporados diretamente no kubeconfig correspondente.
kubeconfig
Todo o kubeconfig necessário pode ser feito usando o Kubernetes da maneira mais difícil , no entanto, aqui algumas diferenças começam. O manual usa configurações de cni bridge
kubedns
e kubedns
, também abrange corns e flanela . Esses dois serviços, por sua vez, usam o kubeconfig
para kubeconfig
no cluster.
$ cd certs
O mestre
Para o assistente, os seguintes arquivos kubeconfig são necessários (como mencionado acima, após a geração eles podem ser obtidos em certs/kubeconfig
):
master /var/lib/kubernetes/$ tree -L 2 . +-- kube-controller-manager.kubeconfig L-- kube-scheduler L-- kube-scheduler.kubeconfig
Esses arquivos serão necessários para executar cada um dos componentes de serviço.
Unidades de Trabalho
Para nós de trabalho, os seguintes arquivos kubeconfig são necessários:
node-1 /var/lib/kubernetes/$ tree -L 2 . +-- coredns ¦ L-- coredns.kubeconfig +-- flanneld ¦ L-- flanneld.kubeconfig +-- kubelet ¦ L-- node-1.kubeconfig L-- kube-proxy L-- kube-proxy.kubeconfig
Lançamento do serviço
ServiçosApesar do fato de meus nós de trabalho usarem sistemas de inicialização diferentes, os exemplos e o repositório oferecem opções usando systemd. Com a ajuda deles, é mais fácil entender qual processo e com quais parâmetros você precisa iniciar; além disso, eles não devem causar grandes problemas ao estudar serviços com sinalizadores de destino.
Para iniciar os serviços, você precisa copiar service-name.service
para /lib/systemd/system/
ou qualquer outro diretório em que os serviços do systemd estejam localizados e, em seguida, ligue e inicie o serviço. Exemplo para kube-apiserver:
$ systemctl enable kube-apiserver.service $ systemctl start kube-apiserver.service
Obviamente, todos os serviços devem ser ecológicos (ou seja, em execução e funcionando). Se você encontrar um erro, os journalct -xe
ou journal -f -t kube-apiserver
ajudarão a entender o que exatamente deu errado.
Não se apresse em iniciar todos os servidores de uma só vez; para começar, será suficiente ativar o etcd e o kube-apiserver. Se tudo correu bem e você ganhou imediatamente todos os quatro serviços no assistente, o lançamento do assistente pode ser considerado bem-sucedido.
O mestre
Você pode usar as configurações do systemd ou gerar scripts init para a configuração que está usando. Como já mencionado, para o mestre você precisa:
- systemd / etcd
- systemd / kube-apiserver
- systemd / kube-controller-manager
- systemd / kube-scheduler
Unidades de Trabalho
- systemd / containerd
- systemd / kubelet
- systemd / kube-proxy
- systemd / coredns
- systemd / flanela
Cliente
Para que o cliente funcione, basta copiar certs/kubeconfig/admin.kubeconfig
(depois de gerá-lo ou gravá-lo você mesmo) em ${HOME}/.kube/config
Faça o download do kubectl e verifique o funcionamento do kube-apiserver. Deixe-me lembrá-lo mais uma vez de que, neste estágio, para que o kube-apiserver funcione, apenas o etcd deve funcionar. Os componentes restantes serão necessários para a operação completa do cluster um pouco mais tarde.
Verifique se o kube-apiserver e o kubectl funcionam:
$ kubectl version Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", "extra info": "..."} Server Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.0", "extra info": "..."}
Configuração de flanela
Como uma configuração de flanela, decidi pelo back-end do vxlan
. Leia mais sobre back-end aqui .
host-gw e por que não vai funcionarDevo dizer imediatamente que a execução de um cluster kubernetes em um VPS provavelmente limitará você a usar o back host-gw
end host-gw
. Não sendo um engenheiro de rede experiente, passei cerca de dois dias depurando para entender qual era o problema com seu uso em provedores populares de VDS / VPS.
Linode.com e digitalocean foram testados. A essência do problema é que os provedores não fornecem L2 honesto para uma rede privada. Isso, por sua vez, torna impossível mover o tráfego de rede entre os nós nesta configuração:

Para que o tráfego de rede funcione entre os nós, o roteamento normal será suficiente. Não esqueça que net.ipv4.ip_forward deve ser definido como 1 e a cadeia FORWARD na tabela de filtros não deve conter regras de proibição para nós.
node1$ ip route add 10.200.12.0/24 via 192.168.1.2 node2$ ip route add 10.200.8.0/24 via 192.168.1.1
[10.200.80.23 container-1]->[192.168.1.1 node-1]->[192.168.1.2 node-2]->[10.200.12.5 container-2]
É exatamente isso que não funciona no VPS / VDS indicado (e, provavelmente, geralmente em todos).
Portanto, se a configuração de uma solução com alto desempenho de rede entre os nós for importante para você, você ainda precisará gastar mais de US $ 20 para organizar o cluster.
Você pode usar o set-flannel-config.sh
do etc / flannel para definir a configuração de flanela desejada. É importante lembrar : se você decidir alterar o back-end, será necessário excluir a configuração no etcd e reiniciar todos os daemons de flanela em todos os nós; portanto, escolha-o com sabedoria. O padrão é vxlan.
master$ export ETCDCTL_CA_FILE='/var/lib/kubernetes/ca.pem' master$ export ETCDCTL_CERT_FILE='/var/lib/kubernetes/kubernetes.pem' master$ export ETCDCTL_KEY_FILE='/var/lib/kubernetes/kubernetes-key.pem' master$ export ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' master$ etcdctl ls /coreos.com/network/subnets/ /coreos.com/network/subnets/10.200.8.0-24 /coreos.com/network/subnets/10.200.12.0-24 master$ etcdctl get /coreos.com/network/subnets/10.200.8.0-24 {"PublicIP":"178.79.168.130","BackendType":"vxlan","BackendData":{"VtepMAC":"22:ca:ac:15:71:59"}}
Depois de registrar a configuração desejada no etcd, você precisa configurar o serviço para executá-lo em cada um dos nós em funcionamento.
flannel.service
Um exemplo para o serviço pode ser obtido aqui: systemd / flannel
flannel.service [Unit] Description=Flanneld overlay address etcd agent After=network.target [Service] Type=notify #: current host ip. don't change if ip have not changed Environment=PUBLIC_IP=178.79.168.130 Environment=FLANNEL_ETCD=https://192.168.153.60:2379 ExecStart=/usr/bin/flanneld \ -etcd-endpoints=${FLANNEL_ETCD} -etcd-prefix=${FLANNEL_ETCD_KEY} \ -etcd-cafile=/var/lib/kubernetes/ca.pem \ -etcd-certfile=/var/lib/kubernetes/kubernetes.pem \ -etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \ -etcd-prefix=/coreos.com/network \ -healthz-ip=127.0.0.1 \ -subnet-file=/run/flannel/subnet.env \ -public-ip=${PUBLIC_IP} \ -kubeconfig-file=/var/lib/kubernetes/config/kubeconfig/flanneld.kubeconfig \ $FLANNEL_OPTIONS ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker Restart=on-failure RestartSec=5 [Install] RequiredBy=docker.service
Personalização
Como descrito anteriormente, precisamos dos arquivos ca.pem, kubernetes.pem e kubernetes-key.pem para autorização no etcd. Todos os outros parâmetros não possuem nenhum significado sagrado. A única coisa que é realmente importante é configurar o endereço IP global através do qual os pacotes de rede irão entre redes:

( Sobreposição de rede de vários hosts com flanela )
Depois que a flanela iniciar com êxito, você deverá encontrar a interface de rede flannel.N em seu sistema:
node-1$ ifconfig flannel.100: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450 inet 10.200.8.0 netmask 255.255.255.255 broadcast 0.0.0.0 inet6 fe80::20ca:acff:fe15:7159 prefixlen 64 scopeid 0x20<link> ether 22:ca:ac:15:71:59 txqueuelen 0 (Ethernet) RX packets 18853 bytes 1077085 (1.0 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 11856 bytes 264331154 (252.0 MiB) TX errors 0 dropped 47 overruns 0 carrier 0 collisions 0
Verificar se suas interfaces estão funcionando corretamente em todos os nós é bastante simples. No meu caso, o nó 1 e o nó 2 têm redes 10.200.8.0/24 e 10.200.12.0/24, respectivamente, portanto, usando uma solicitação icmp normal, verifique sua disponibilidade:
#: node-2 node-1 node-1 $ ping -c 1 10.200.12.0 PING 10.200.12.0 (10.200.12.0) 56(84) bytes of data. 64 bytes from 10.200.12.0: icmp_seq=1 ttl=64 time=4.58 ms #: node-1 node-2 node-2 $ ping -c 1 10.200.8.0 PING 10.200.8.0 (10.200.8.0) 56(84) bytes of data. 64 bytes from 10.200.8.0: icmp_seq=1 ttl=64 time=1.44 ms
Em caso de problemas, é recomendável verificar se existem regras de corte nas tabelas de ip sobre UDP entre hosts.
Configuração Containerd
Coloque o arquivo etc / containserd / config.toml em /etc/containerd/config.toml
ou sempre que for conveniente para você, o principal é lembrar de alterar o caminho para o arquivo de configuração no serviço (containerd.service, descrito abaixo).
Configuração com algumas modificações do padrão. É importante não definir enable_tls_streaming = true
se você não entender por que está fazendo isso. kubectl exec
, .
containerd.service
containerd.service [Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target [Service] ; uncomment this if your overlay module are built as module ; ExecStartPre=/sbin/modprobe overlay ExecStart=/usr/bin/containerd \ -c /etc/containerd/config.toml Restart=always RestartSec=5 Delegate=yes KillMode=process OOMScoreAdjust=-999 LimitNOFILE=1048576 LimitNPROC=infinity LimitCORE=infinity [Install] WantedBy=multi-user.target
Personalização
, , cri-tools .
etc/crictl.yaml /etc/crictl.yaml
. :
node-1$ CONTAINERD_NAMESPACE=k8s.io crictl ps CONTAINER ID IMAGE CREATED STATE NAME ATTEMPT POD ID
, - kubernetes , crictl , , .
CNI Plugins
CNI , , , .
Personalização
cni plugins /opt/cni/bin/
/etc/cni/net.d :
/etc/cni/net.d/10-flannel.conflist { "cniVersion": "0.3.0", "name": "cbr0", "plugins": [ { "type": "flannel", "name": "kubenet", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true }, "externalSetMarkChain": "KUBE-MARK-MASQ" } ] }
/etc/cni/net.d/99-loopback.conf { "cniVersion": "0.3.0", "type": "loopback" }
, . , , Red Hat Docker Podman , Intro to Podman
Kubelet
kubelet ( cni) — . kubelet hostname. , "" kubectl logs
, kubectl exec
, kubectl port-forward
.
kubelet-config.yaml, etc/kubelet-config.yaml , , . :
systemReserved: cpu: 200m memory: 600Mi
, GO kubernetes, , . . 0.2 vCPU 600 MB .
, , kubelet, kube-proxy, coredns, flannel . , — 2 vCPU / 4G ram, , kubernetes + postgresql .
- (micro nodes) .
kubelet.service
service : systemd/kubelet
kubelet.service [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/kubernetes/kubernetes Requires=containerd.service [Service] #Environment=NODE_IP=192.168.164.230 Environment=NODE_IP=178.79.168.130 #: node name given by env Environment=NODE_NAME=w40k.net ExecStart=kubelet \ --allow-privileged \ --root-dir=/var/lib/kubernetes/kubelet \ --config=/var/lib/kubernetes/kubelet/kubelet-config.yaml \ --kubeconfig=/var/lib/kubernetes/kubelet/node-1.kubeconfig \ --cni-bin-dir=/opt/cni/bin \ --cni-conf-dir=/etc/cni/net.d/ \ --network-plugin=cni \ --container-runtime=remote \ --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \ --image-pull-progress-deadline=10m \ --node-ip=${NODE_IP} \ --hostname-override=${NODE_NAME} \ --v=1 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
Personalização
, RBAC , kubelet.
etc/kubelet-default-rbac.yaml , kubelet :
user$ kubectl apply -f etc/kubelet-default-rbac.yaml
, , .
, api :
$ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME w40k.net Ready <none> 5m v1.13.1 178.79.168.130 <none> Gentoo/Linux 4.18.16-x86_64-linode118 containerd://1.2.1
Kube Proxy
: systemd/kubelet . , , kube-proxy-config.yaml
: etc/kube-proxy
kube-proxy.service
kube-proxy.service [Unit] Description=Kubernetes Proxy Documentation=https://github.com/kubernetes/kubernetes After=network.target [Service] ExecStart=kube-proxy \ --config=/var/lib/kubernetes/kube-proxy/kube-proxy-config.yaml Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
Personalização
kube-proxy "" iptables, , - kubernetes (- ). .
CoreDNS
Corefile : etc/coredns/Corefile , :
/etc/coredns/Corefile .:53 { errors log stdout health :8081 kubernetes cluster.local 10.200.0.0/16 { endpoint https://178.79.148.185:6443 tls /var/lib/kubernetes/kubernetes.pem /var/lib/kubernetes/kubernetes-key.pem /var/lib/kubernetes/ca.pem pods verified upstream /etc/resolv.conf kubeconfig /var/lib/kubernetes/config/kubeconfig/coredns.kubeconfig default } proxy . /etc/resolv.conf cache 30 }
coredns.kubeconfig pem- ( ) worker . , coredns systemd-resolved. , Ubuntu , , , , . .
coredns.service
coredns.service [Unit] Description=CoreDNS Documentation=https://coredns.io/ After=network.target [Service] ExecStart=/usr/bin/coredns -conf /etc/coredns/Corefile Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
Personalização
, , :
node-1$ dig kubernetes.default.svc.cluster.local @127.0.0.1 #: ;kubernetes.default.svc.cluster.local. IN A ;; ANSWER SECTION: kubernetes.default.svc.cluster.local. 5 IN A 10.32.0.1
, coredns ip kubernetes .
, kubernetes.default kube-controller-manager, :
$ kubectl get svc -n default NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.32.0.1 <none> 443/TCP 26h
nginx-ingress & cert-manager
, . nginx-ingress cert-manager.
— nginx kubernetes ingress (master), :
user$ git clone https://github.com/nginxinc/kubernetes-ingress.git user$ cd kubernetes-ingress/deployments user$ kubectl apply -f common/ns-and-sa.yaml user$ kubectl apply -f common/nginx-config.yaml user$ kubectl apply -f common/default-server-secret.yaml user$ kubectl apply -f daemon-set/nginx-ingress.yaml user$ kubectl apply -f rbac/rbac.yaml
— cert manager (v0.5.2)
user$ git clone https://github.com/jetstack/cert-manager.git user$ cd cert-manager && git co v0.5.2 user$ cd contrib/manifests/cert-manager user$ kubectl apply -f with-rbac.yaml
, , , :
NAMESPACE NAME READY STATUS RESTARTS AGE cert-manager cert-manager-554c76fbb7-t9762 1/1 Running 0 3h38m nginx-ingress nginx-ingress-sdztf 1/1 Running 0 10h nginx-ingress nginx-ingress-vrf85 1/1 Running 0 10h
cert-manager nginx-ingress running state, , . , Running
. .
, . , kubernetes resource : app/k8s
user$ kube apply -f ns-and-sa.yaml user$ kube apply -f configmap.yaml
, - . , ( kubernetes-example.w40k.net), , , cert-manager nginx-ingress . , ingress tls/ssl.
:
, - . - , , .
Referências
, , :
— Kubernetes the hard way
— Multi-Host Networking Overlay with Flannel
— Intro to Podman
— Stateless Applications
— What is ingress
:
— Kubernetes Networking: Behind the scenes ( )
— A Guide to the Kubernetes Networking Model
— Understanding kubernetes networking: services ( )
Q&A
<tbd>, .
, , . , , - , , .
Api Server
kube-apiserver.service
, api-server' curl http . - .
admin.kubeconfig ${HOME}/.kube/config, kubectl api-server (kube-apiserver).
( ) HTTP 200 OK + , api-server :
curl -H "Authorization: Bearer e5qXNAtwwCHUUwyLilZmAoFPozrQwUpw" -k -L https://<api-server-address>:6443/api/v1/
Kube Controller Manager
, controller manager api , . , service account' :
$ kubectl get sa NAME SECRETS AGE default 1 19h
, , kube-controller-manager .
Kube Scheduler
. , , debug/job.yaml kubectl describe <type/resource>
.
, kube controller manager .
#: job user$ kubectl apply -f debug/job.yaml job.batch/app created #: , job user$ kubectl get pods -l job-name=app NAME READY STATUS RESTARTS AGE app-9kr9z 0/1 Completed 0 54s #: , #: user$ kubectl describe pods app-9kr9z # ... ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 12s default-scheduler Successfully assigned example/app-9kr9z to w40k.net
, default-scheduler pod w40k.net. - , — .
. , , , — "". systemd .
kube scheduler
Kubelet
Kubelet kubernetes . kubelet . kubernetes event ( kubectl get events -o wide
) .
( )
Kube Proxy
kube-proxy :
- ( Flannel , );
- iptables, filter nat .
, 10.32.0.0/24 "". , . iptables, , , - +. icmp , ping' . , .
, kube-proxy, :
#: user$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE backend ClusterIP 10.32.0.195 <none> 80/TCP 5m #: user$ kubectl get pods -o wide #: ' NAME READY STATUS RESTARTS AGE IP NODE backend-896584448-4r94s 1/1 Running 0 11h 10.200.8.105 w40k.net backend-896584448-np992 1/1 Running 0 11h 10.200.12.68 docker.grart.net #: 10 /status/ endpoint , #: node-1$ for i in `seq 10`; do curl -L http://10.32.0.195/status/; done okokokokokokokokokok node-1$ conntrack -L -d 10.32.0.195 tcp 6 62 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62158 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62158 [ASSURED] mark=0 use=1 tcp 6 60 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62144 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62144 [ASSURED] mark=0 use=1 tcp 6 58 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62122 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62122 [ASSURED] mark=0 use=1 tcp 6 59 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62142 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62142 [ASSURED] mark=0 use=1 tcp 6 58 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62130 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62130 [ASSURED] mark=0 use=1 tcp 6 61 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62150 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62150 [ASSURED] mark=0 use=1 tcp 6 56 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62116 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62116 [ASSURED] mark=0 use=1 tcp 6 57 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62118 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62118 [ASSURED] mark=0 use=1 tcp 6 59 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62132 dport=80 src=10.200.12.68 dst=10.200.8.0 sport=8000 dport=62132 [ASSURED] mark=0 use=1 tcp 6 56 TIME_WAIT src=178.79.168.130 dst=10.32.0.195 sport=62114 dport=80 src=10.200.8.105 dst=10.200.8.1 sport=8000 dport=62114 [ASSURED] mark=0 use=1
src/dst (9 10 ). , src :
, . , - ( , ) . .
, , conntrack , , kube-proxy. , nat :
node-1$ iptables -t nat -vnL
.
. , , . , . - , , .