DEV Community

Marcello Alexandre
Marcello Alexandre

Posted on

Configurando Kind Cluster com Cilium e sem kube-proxy: Um Guia Prático

Introdução

Este tutorial é uma tradução e atualização do post original "Kind cluster with Cilium and no kube-proxy" de Charles-Edouard Brétéché. Ele foi adaptado para funcionar com algumas mudanças mais recentes na configuração. Gostaria de agradecer a Charles-Edouard Brétéché por seu excelente trabalho e por compartilhar seus conhecimentos.
I would like to thank Charles-Edouard Brétéché for his excellent work and for sharing his knowledge.

Configurar um cluster Kubernetes com Kind (Kubernetes em Docker) é uma escolha popular para desenvolvimento e testes locais. O Kind cria um cluster Kubernetes executando contêineres Docker como nós. Neste tutorial, vamos configurar um cluster Kind com Cilium como a CNI (Interface de Rede de Contêineres) e sem kube-proxy.

Visão Geral do Kind

O Kind é uma maneira simples e eficaz de executar clusters Kubernetes locais compostos por vários nós.

Kind é uma ferramenta para executar clusters Kubernetes locais usando contêineres Docker como "nós". O Kind foi projetado principalmente para testar o próprio Kubernetes, mas também pode ser usado para desenvolvimento local ou CI (Integração Contínua).

O Kind vem com um CNI (Container Network Interface) padrão chamado kindnet. Este CNI simples cuida das noções básicas de rede, mas não suporta recursos avançados como NetworkPolicy.

Visão Geral do Cilium

Cilium é uma CNI moderna e avançada para Kubernetes, implementada sobre o eBPF, que foca em desempenho, segurança e observabilidade.

Cilium é um software de código aberto para fornecer, proteger e observar a conectividade de rede entre cargas de trabalho em contêineres — nativo da nuvem e alimentado pela revolucionária tecnologia do Kernel, eBPF.

NetworkPolicy padrão, bem como as mais avançadas CiliumNetworkPolicy e CiliumClusterwideNetworkPolicy, são suportadas. Ele oferece capacidades de múltiplos clusters, permite a observação das atividades de rede e muito mais.

Combinando Kind e Cilium

Felizmente, o Kind pode ser configurado para usar outra CNI além do kindnet. Neste artigo, vamos passar pelos passos necessários para usar o Cilium CNI em clusters alimentados pelo Kind.

Uma característica do Cilium é que ele pode substituir completamente o kube-proxy. Com a configuração correta, os clusters do Kind podem ser configurados para usar a Cilium CNI e funcionar com o kube-proxy desativado.

Executar um cluster desse tipo localmente ajuda a configurar um ambiente local mais próximo de um cluster de produção real. Isso nos permite testar coisas que não poderiam ser testadas com o kindnet.


Um cluster sem CNI e com kube-proxy desativado

Ao criar um cluster Kind, é possível fornecer uma especificação do cluster com a configuração do cluster. A seção de rede permite configurar a CNI padrão do cluster e outros componentes do cluster.

Executar o comando abaixo irá iniciar um cluster sem kindnet e não instalará o kube-proxy:

Observação: Por experiência própria, pode ocorrer um erro ao tentar criar esse cluster se você não tiver uma máquina tão potente ou com pouco recurso disponível. É recomendado diminuir a quantidade de workers.

kind create cluster --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  disableDefaultCNI: true   # não instala kindnet
  kubeProxyMode: none       # não executa kube-proxy
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
EOF
Enter fullscreen mode Exit fullscreen mode

Claro, esse cluster não será utilizável. Os nós permanecerão no estado NotReady até que uma CNI seja instalada. Você pode verificar o status dos nodes executando o comando kubectl get nodes:

NAME                 STATUS     ROLES                  AGE   VERSION
kind-control-plane   NotReady   control-plane,master   57s   v1.27.3
kind-worker          NotReady   <none>                 21s   v1.27.3
kind-worker2         NotReady   <none>                 21s   v1.27.3
kind-worker3         NotReady   <none>                 21s   v1.27.3
Enter fullscreen mode Exit fullscreen mode

Instalar Cilium

Instalar o Cilium no cluster criado anteriormente deve ajudar a tornar o cluster utilizável. No entanto, não será tão simples.

Como o kube-proxy não está em execução, não é possível se comunicar com o API server usando o Kubernetes service dentro do cluster.

Observação: Caso não funcionem a instalação, é sempre bom verificar a documentação do Cilium.

Por enquanto, vamos instalar o Cilium e ver onde as coisas falham. O Cilium pode ser instalado com Helm e junto a uma configuração:

helm upgrade --install --namespace kube-system --repo https://helm.cilium.io cilium cilium --values - <<EOF
kubeProxyReplacement: true
hostServices:
  enabled: false
externalIPs:
  enabled: true
nodePort:
  enabled: true
hostPort:
  enabled: true
image:
  pullPolicy: IfNotPresent
ipam:
  mode: kubernetes
hubble:
  enabled: true
  relay:
    enabled: true
EOF
Enter fullscreen mode Exit fullscreen mode

Neste ponto, o Cilium deve começar a ser instalado no cluster:

NAMESPACE            NAME                                         READY   STATUS              RESTARTS   AGE
kube-system          cilium-6szjr                                 0/1     Running             0          7s
kube-system          cilium-operator-6fb8dbd88c-2p4mv             1/1     Running             0          7s
kube-system          cilium-operator-6fb8dbd88c-mdrg9             1/1     Running             0          7s
kube-system          cilium-sw9d5                                 0/1     Running             0          7s
kube-system          cilium-zxgfx                                 0/1     Running             0          7s
Enter fullscreen mode Exit fullscreen mode

Infelizmente, os pods do cilium-operator e dos agents do Cilium nunca se tornarão Ready e reiniciarão continuamente:

kube-system          cilium-operator-6fb8dbd88c-2p4mv             0/1     Error               4          6m43s
kube-system          cilium-operator-6fb8dbd88c-2p4mv             0/1     CrashLoopBackOff    4          6m50s
kube-system          cilium-6szjr                                 0/1     Error               1          2m10s
kube-system          cilium-zxgfx                                 0/1     Error               1          2m10s
kube-system          cilium-sw9d5                                 0/1     Error               1          2m10s
kube-system          cilium-6szjr                                 0/1     CrashLoopBackOff    1          2m12s
kube-system          cilium-zxgfx                                 0/1     CrashLoopBackOff    1          2m12s
kube-system          cilium-sw9d5                                 0/1     CrashLoopBackOff    1          2m12s
kube-system          cilium-operator-6fb8dbd88c-mdrg9             1/1     Running             3          6m59s
kube-system          cilium-dqknq                                 0/1     Error               1          2m10s
kube-system          cilium-dqknq                                 0/1     CrashLoopBackOff    1          2m12s
Enter fullscreen mode Exit fullscreen mode

Analisar os logs do operador ou dos agentes explicará o que está acontecendo:

level=info msg="Cilium Operator 1.11.1 76d34db 2022-01-18T15:52:51-08:00 go version go1.17.6 linux/amd64" subsys=cilium-operator-generic
level=info msg="Establishing connection to apiserver" host="https://10.96.0.1:443" subsys=k8s
level=info msg="Starting apiserver on address 127.0.0.1:9234" subsys=cilium-operator-api
level=info msg="Establishing connection to apiserver" host="https://10.96.0.1:443" subsys=k8s
level=error msg="Unable to contact k8s api-server" error="Get \"https://10.96.0.1:443/api/v1/namespaces/kube-system\": dial tcp 10.96.0.1:443: connect: connection refused" ipAddr="https://10.96.0.1:443" subsys=k8s
level=fatal msg="Unable to connect to Kubernetes apiserver" error="unable to create k8s client: unable to create k8s client: Get \"https://10.96.0.1:443/api/v1/namespaces/kube-system\": dial tcp 10.96.0.1:443: connect: connection refused" subsys=cilium-operator-generic
Enter fullscreen mode Exit fullscreen mode

O operador e os agentes não conseguem se comunicar com o node control plane do Kubernetes. Isso ocorre porque o kube-proxy não está instalado no cluster e, portanto, o Kubernetes service dentro do cluster não pode ser alcançado.


Configurar o endpoint do Kubernetes service para Cilium

Para resolver o problema anterior em que os pods do Cilium não conseguem se conectar ao API server do Kubernetes, precisamos configurar o API server do cluster para ouvir em um endereço IP que possa ser acessado pelos pods do Cilium.

O Kind executa os nodes do cluster em contêineres Docker em uma rede dedicada. Os contêineres em execução na rede do kind podem resolver os endereços IP de outros contêineres pelo nome.

Se observarmos os contêineres Docker iniciados pelo Kind com o comando docker ps, deveríamos ver algo assim:

CONTAINER ID   IMAGE                  NAMES
b4badebf3db8   kindest/node:v1.27.3   kind-worker3
195cfd2b59e7   kindest/node:v1.27.3   kind-worker
81de0b8dbf18   kindest/node:v1.27.3   kind-control-plane
9f4b82ee120b   kindest/node:v1.27.3   kind-worker2
Enter fullscreen mode Exit fullscreen mode

O contêiner kind-control-plane é nosso nó mestre do Kubernetes e executa o API server (na porta 6443). Enquanto estivermos nos contêineres em execução na rede do kind, o nome kind-control-plane deve ser resolvível. Podemos usá-lo para configurar o endpoint do API server do Kubernetes usado pelos pods do Cilium:

helm upgrade --install --namespace kube-system --repo https://helm.cilium.io cilium cilium --values - <<EOF
kubeProxyReplacement: true
k8sServiceHost: kind-control-plane # node mestre na rede do kind
k8sServicePort: 6443               # porta do API server
hostServices:
  enabled: false
externalIPs:
  enabled: true
nodePort:
  enabled: true
hostPort:
  enabled: true
image:
  pullPolicy: IfNotPresent
ipam:
  mode: kubernetes
hubble:
  enabled: true
  relay:
    enabled: true
EOF
Enter fullscreen mode Exit fullscreen mode

Após algum tempo, os pods do Cilium e os nodes do cluster devem se tornar Ready.


Instalar um ingress controller

Neste ponto, o cluster deve estar em execução, utilizando Cilium CNI, sem kube-proxy, e tudo deve funcionar conforme o esperado.

Para obter algo útil dele, agora devemos instalar um ingress controller e o Cilium Hubble UI para visualizar a rede no cluster.

Vamos instalar o ingress-nginx e usar o nip.io para acessar o Hubble UI em execução dentro do cluster.

Isso requer configurar a especificação do cluster kind para expor portas adicionais do host e permitir que nosso ingress controller receba tráfego:

kind delete cluster && kind create cluster --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  disableDefaultCNI: true
  kubeProxyMode: none
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    listenAddress: 127.0.0.1
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    listenAddress: 127.0.0.1
    protocol: TCP
- role: worker
- role: worker
- role: worker
EOF
Enter fullscreen mode Exit fullscreen mode

Você pode conferir a nova label atraves de kubectl get nodes --show-labels=true

NAME                 STATUS   ROLES           AGE   VERSION   LABELS
kind-control-plane   Ready    control-plane   13h   v1.27.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress-ready=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=kind-control-plane,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
kind-worker          Ready    <none>          13h   v1.27.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kind-worker,kubernetes.io/os=linux
kind-worker2         Ready    <none>          13h   v1.27.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kind-worker2,kubernetes.io/os=linux
kind-worker3         Ready    <none>          13h   v1.27.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kind-worker3,kubernetes.io/os=linux
Enter fullscreen mode Exit fullscreen mode

Instale o Cilium com o Hubble UI habilitado e acessível em ingress hubble-ui.127.0.0.1.nip.io:

helm upgrade --install --namespace kube-system --repo https://helm.cilium.io cilium cilium --values - <<EOF
kubeProxyReplacement: true
k8sServiceHost: kind-control-plane
k8sServicePort: 6443
hostServices:
  enabled: false
externalIPs:
  enabled: true
nodePort:
  enabled: true
hostPort:
  enabled: true
image:
  pullPolicy: IfNotPresent
ipam:
  mode: kubernetes
hubble:
  enabled: true
  relay:
    enabled: true
  ui:
    enabled: true
    ingress:
      enabled: true
      annotations:
        kubernetes.io/ingress.class: nginx
      hosts:
        - hubble-ui.127.0.0.1.nip.io
EOF
Enter fullscreen mode Exit fullscreen mode

Por fim, instale o ingress controller ingress-nginx:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.1/deploy/static/provider/kind/deploy.yaml
Enter fullscreen mode Exit fullscreen mode

Observação: Talvez seja necessário alterar as tolerations para garantir que o ingress controller seja agendado corretamente nos nós do cluster. Você pode fazer isso adicionando a seguinte configuração ao seu pod:

kubectl edit deploy -n ingress-nginx ingress-nginx-controller 
Enter fullscreen mode Exit fullscreen mode
      tolerations:
        - effect: NoSchedule
          key: node-role.kubernetes.io/control-plane 
          operator: Equal 
Enter fullscreen mode Exit fullscreen mode

Após algum tempo:

  • Os pods do Cilium devem ficar Ready
  • O ingress controller ingress-nginx deve ser escalonado no cluster
  • O Hubble UI deve ser acessível em http://hubble-ui.127.0.0.1.nip.io 🎉

Image description

Billboard image

Deploy and scale your apps on AWS and GCP with a world class developer experience

Coherence makes it easy to set up and maintain cloud infrastructure. Harness the extensibility, compliance and cost efficiency of the cloud.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Engage with a sea of insights in this enlightening article, highly esteemed within the encouraging DEV Community. Programmers of every skill level are invited to participate and enrich our shared knowledge.

A simple "thank you" can uplift someone's spirits. Express your appreciation in the comments section!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found this useful? A brief thank you to the author can mean a lot.

Okay