K8S The Hard Way 6/10 - Control Plane

Tue, Feb 23, 2021 7-minute read

Inicializando o cluster etcd

Os componentes do Kubernetes não têm estado de armazenam, tudo é armazenado no cluster etcd. Neste laboratório, você inicializará um cluster etcd de três nodes e o configurará alta disponibilidade e acesso remoto seguro.

Pré-requisitos

Os comandos neste laboratório devem ser executados em cada controller: controlador-0, controlador-1 e controlador-2. Faça login em cada instância usando o comando vagrant ssh . Exemplo:

vagrant ssh controller-0

Executando comandos em paralelo com tmux

O tmux pode ser usado para executar comandos em várias instâncias de computação ao mesmo tempo. Consulte a seção Executando comandos em paralelo com tmux no laboratório de pré-requisitos.

Provisione o plano de controle do Kubernetes

Crie o diretório de configuração do Kubernetes:

sudo mkdir -p /etc/kubernetes/config

Baixe e instale os binários dos controllers:

Baixe os binários de lançamento oficiais do Kubernetes:

wget -q --show-progress --https-only --timestamping \
  "https://storage.googleapis.com/kubernetes-release/release/v1.18.6/bin/linux/amd64/kube-apiserver" \
  "https://storage.googleapis.com/kubernetes-release/release/v1.18.6/bin/linux/amd64/kube-controller-manager" \
  "https://storage.googleapis.com/kubernetes-release/release/v1.18.6/bin/linux/amd64/kube-scheduler" \
  "https://storage.googleapis.com/kubernetes-release/release/v1.18.6/bin/linux/amd64/kubectl"

Install the Kubernetes binaries:

  chmod +x kube-apiserver kube-controller-manager kube-scheduler kubectl
  sudo mv kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/local/bin/

Configure the Kubernetes API Server

  sudo mkdir -p /var/lib/kubernetes/

  sudo mv ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \
    service-account-key.pem service-account.pem \
    encryption-config.yaml /var/lib/kubernetes/

O endereço IP interno da instância será usado para anunciar o API Server aos membros do cluster. Recupere o endereço IP interno da instância de computação atual:

INTERNAL_IP=`echo $SSH_CONNECTION | awk -F " " '{print $3}'`

Create the kube-apiserver.service systemd unit file:

CONTROLLER0=`dig +short controller-0 | grep -v "127.0.1.1" | xargs`
CONTROLLER1=`dig +short controller-1 | grep -v "127.0.1.1" | xargs`
CONTROLLER2=`dig +short controller-2 | grep -v "127.0.1.1" | xargs`

cat <<EOF | sudo tee /etc/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-apiserver \\
  --advertise-address=${INTERNAL_IP} \\
  --allow-privileged=true \\
  --apiserver-count=3 \\
  --audit-log-maxage=30 \\
  --audit-log-maxbackup=3 \\
  --audit-log-maxsize=100 \\
  --audit-log-path=/var/log/audit.log \\
  --authorization-mode=Node,RBAC \\
  --bind-address=0.0.0.0 \\
  --client-ca-file=/var/lib/kubernetes/ca.pem \\
  --enable-admission-plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \\
  --etcd-cafile=/var/lib/kubernetes/ca.pem \\
  --etcd-certfile=/var/lib/kubernetes/kubernetes.pem \\
  --etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \\
  --etcd-servers=https://$CONTROLLER0:2379,https://$CONTROLLER1:2379,https://$CONTROLLER2:2379 \\
  --event-ttl=1h \\
  --encryption-provider-config=/var/lib/kubernetes/encryption-config.yaml \\
  --kubelet-certificate-authority=/var/lib/kubernetes/ca.pem \\
  --kubelet-client-certificate=/var/lib/kubernetes/kubernetes.pem \\
  --kubelet-client-key=/var/lib/kubernetes/kubernetes-key.pem \\
  --kubelet-https=true \\
  --runtime-config='api/all=true' \\
  --service-account-key-file=/var/lib/kubernetes/service-account.pem \\
  --service-cluster-ip-range=10.32.0.0/24 \\
  --service-node-port-range=30000-32767 \\
  --tls-cert-file=/var/lib/kubernetes/kubernetes.pem \\
  --tls-private-key-file=/var/lib/kubernetes/kubernetes-key.pem \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Configure kube-controller-manager

Mova o kube-controller-manager kubeconfig para o diretório:

sudo mv kube-controller-manager.kubeconfig /var/lib/kubernetes/

Crie o kube-controller-manager.service para o systemd:

cat <<EOF | sudo tee /etc/systemd/system/kube-controller-manager.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-controller-manager \\
  --bind-address=0.0.0.0 \\
  --cluster-cidr=10.200.0.0/16 \\
  --cluster-name=kubernetes \\
  --cluster-signing-cert-file=/var/lib/kubernetes/ca.pem \\
  --cluster-signing-key-file=/var/lib/kubernetes/ca-key.pem \\
  --kubeconfig=/var/lib/kubernetes/kube-controller-manager.kubeconfig \\
  --leader-elect=true \\
  --root-ca-file=/var/lib/kubernetes/ca.pem \\
  --service-account-private-key-file=/var/lib/kubernetes/service-account-key.pem \\
  --service-cluster-ip-range=10.32.0.0/24 \\
  --use-service-account-credentials=true \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Configure kube-scheduler

Move the kube-scheduler kubeconfig into place:

sudo mv kube-scheduler.kubeconfig /var/lib/kubernetes/

Crie o arquivo de configuração kube-scheduler.yaml:

cat <<EOF | sudo tee /etc/kubernetes/config/kube-scheduler.yaml
apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
clientConnection:
  kubeconfig: "/var/lib/kubernetes/kube-scheduler.kubeconfig"
leaderElection:
  leaderElect: true
EOF

Crie o kube-scheduler.service systemd:

cat <<EOF | sudo tee /etc/systemd/system/kube-scheduler.service
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-scheduler \\
  --config=/etc/kubernetes/config/kube-scheduler.yaml \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Inicie os serviços do controlador

  sudo systemctl daemon-reload
  sudo systemctl enable kube-apiserver kube-controller-manager kube-scheduler
  sudo systemctl start kube-apiserver kube-controller-manager kube-scheduler

Aguarde até 10 segundos para que o servidor da API Kubernetes seja totalmente inicializado.

Habilitar verificações de saúde de HTTP

Um balanceador de carga será usado para distribuir o tráfego entre os três servidores de API e permitir que cada servidor de API encerre as conexões TLS e valide os certificados do cliente. O balanceador de carga de rede só oferece suporte a verificações de integridade HTTP, o que significa que o ponto de extremidade HTTPS exposto pelo servidor de API não pode ser usado. Como solução alternativa, o servidor da web nginx pode ser usado para fazer proxy de verificações de integridade HTTP. Nesta seção, o nginx será instalado e configurado para aceitar verificações de integridade HTTP na porta 80 e fazer proxy das conexões com o servidor API em https://127.0.0.1:6443/healthz.

O ponto de extremidade do servidor da API / healthz não requer autenticação por padrão.

Instale um servidor da web básico para lidar com as verificações de integridade HTTP:

sudo apt-get update
sudo apt-get install -y nginx
cat > kubernetes.default.svc.cluster.local <<EOF
server {
  listen      80;
  server_name kubernetes.default.svc.cluster.local;

  location /healthz {
     proxy_pass                    https://127.0.0.1:6443/healthz;
     proxy_ssl_trusted_certificate /var/lib/kubernetes/ca.pem;
  }
}
EOF
  sudo mv kubernetes.default.svc.cluster.local \
    /etc/nginx/sites-available/kubernetes.default.svc.cluster.local

  sudo ln -s /etc/nginx/sites-available/kubernetes.default.svc.cluster.local /etc/nginx/sites-enabled/
sudo systemctl restart nginx
sudo systemctl enable nginx

Verificação:

kubectl get componentstatuses --kubeconfig admin.kubeconfig

Saida:

NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
etcd-2               Healthy   {"health":"true"}   
etcd-1               Healthy   {"health":"true"}   
etcd-0               Healthy   {"health":"true"}   

Teste o proxy de verificação de integridade HTTP nginx:

curl -H "Host: kubernetes.default.svc.cluster.local" -i http://127.0.0.1/healthz

Saída

HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sat, 18 Jul 2020 06:20:48 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 2
Connection: keep-alive
Cache-Control: no-cache, private
X-Content-Type-Options: nosniff

ok

Lembre-se de executar os comandos acima em cada nó do controlador: controlador-0, controlador-1 e controlador-2.

RBAC para autorização Kubelet

Nesta seção, você configurará as permissões RBAC para permitir que o servidor da API Kubernetes acesse a API Kubelet em cada nó de trabalho. O acesso à API Kubelet é necessário para recuperar métricas, registros e executar comandos em pods.

Este tutorial define o sinalizador Kubelet –authorization-mode como Webhook. O modo Webhook usa a API SubjectAccessReview para determinar a autorização.

Os comandos nesta seção afetarão todo o cluster e só precisam ser executados uma vez a partir de um dos nós do controlador.

vagrant ssh controller-0

Crie o sistema: kube-apiserver-to-kubelet ClusterRole com permissões para acessar a API Kubelet e realizar as tarefas mais comuns associadas ao gerenciamento de pods:

cat <<EOF | kubectl apply --kubeconfig admin.kubeconfig -f -
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:kube-apiserver-to-kubelet
rules:
  - apiGroups:
      - ""
    resources:
      - nodes/proxy
      - nodes/stats
      - nodes/log
      - nodes/spec
      - nodes/metrics
    verbs:
      - "*"
EOF

O servidor da API do Kubernetes se autentica no Kubelet como o usuário do kubernetes usando o certificado do cliente, conforme definido pela sinalização –kubelet-client-certificate.

Vincule o sistema: kube-apiserver-to-kubelet ClusterRole ao usuário kubernetes:

cat <<EOF | kubectl apply --kubeconfig admin.kubeconfig -f -
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: system:kube-apiserver
  namespace: ""
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:kube-apiserver-to-kubelet
subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: kubernetes
EOF

Balanceador de carga front-end do Kubernetes

Nesta seção, você provisionará um balanceador de carga externo na frente dos servidores da API Kubernetes. O endereço IP será anexado ao balanceador de carga.

Provisionar um balanceador de carga de rede Crie os recursos de rede do balanceador de carga externo:

vagrant ssh loadbalancer

Instalação do HAProxy:

sudo apt-get update ; sudo apt-get install -y haproxy vim

Editar o arquivo de configuração /etc/haproxy/haproxy.cfg:

CONTROLLER0=`dig +short controller-0 | grep -v "127.0.1.1" | xargs`
CONTROLLER1=`dig +short controller-1 | grep -v "127.0.1.1" | xargs`
CONTROLLER2=`dig +short controller-2 | grep -v "127.0.1.1" | xargs`

cat <<EOF | sudo tee /etc/haproxy/haproxy.cfg
global
        log /dev/log    local0
        log /dev/log    local1 notice
        chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
        stats timeout 30s
        user haproxy
        group haproxy
        daemon

        # Default SSL material locations
        ca-base /etc/ssl/certs
        crt-base /etc/ssl/private

        # See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
        ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
        ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
        ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults                 
        log     global   
        mode    tcp      
        option  tcplog   
        option  dontlognull
        timeout connect 5000
        timeout client  50000
        timeout server  50000
        errorfile 400 /etc/haproxy/errors/400.http
        errorfile 403 /etc/haproxy/errors/403.http
        errorfile 408 /etc/haproxy/errors/408.http
        errorfile 500 /etc/haproxy/errors/500.http
        errorfile 502 /etc/haproxy/errors/502.http
        errorfile 503 /etc/haproxy/errors/503.http
        errorfile 504 /etc/haproxy/errors/504.http

frontend proxynode                                    
        bind *:80                                     
        bind *:6443                                   
        stats uri /proxystats                         
        default_backend k8sServers          

#<-- Add the following lines to bottom of file        
backend k8sServers                                    
        balance roundrobin                            
        server controller-0 $CONTROLLER0:6443 check
        server controller-1 $CONTROLLER1:6443 check
        server controller-2 $CONTROLLER2:6443 check

listen stats                                          
        bind :9999                                    
        mode http                                     
        stats enable                                  
        stats hide-version                            
        stats uri /stats                              
EOF

Inicie o serviço de loadbalance:

sudo systemctl enable haproxy
sudo systemctl start haproxy

Recupere o endereço IP estático do locabalancer:

KUBERNETES_PUBLIC_ADDRESS=`sudo vagrant ssh-config loadbalancer | grep HostName | xargs  | sed 's/HostName//g' | xargs`

Faça uma solicitação HTTP para as informações da versão do Kubernetes:

curl --cacert ca.pem https://${KUBERNETES_PUBLIC_ADDRESS}:6443/version

Saída

{
  "major": "1",
  "minor": "18",
  "gitVersion": "v1.18.6",
  "gitCommit": "dff82dc0de47299ab66c83c626e08b245ab19037",
  "gitTreeState": "clean",
  "buildDate": "2020-07-15T16:51:04Z",
  "goVersion": "go1.13.9",
  "compiler": "gc",
  "platform": "linux/amd64"
}

Proximo: K8S The Hard Way 7/10 - Workers