Skip to main content

Kubeadm


사전 작업

  • 최소 필요 조건
    • 2 CPU
    • 2 GB memory
    • 모든 노드에 대한 고유한 호스트 이름, MAC 주소, prodcut_uuid
      • ip link
      • sudo cat /sys/class/dmi/id/product_uuid
kubeadm-installation.yaml
---
- hosts: all
become: yes
vars:
version: 1.19.15-00
tasks:
- name: Install requirements
apt:
name: "{{ item }}"
state: latest
update_cache: yes
loop: ["apt-transport-https", "ca-certificates", "curl"]

- name: Add kubernetes GPG apt key
apt_key:
url: https://packages.cloud.google.com/apt/doc/apt-key.gpg
keyring: /usr/share/keyrings/kubernetes-archive-keyring.gpg

- name: Add kubernetes repository
apt_repository:
repo: deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg]
https://apt.kubernetes.io/ kubernetes-xenial main
filename: kubernetes

- name: Install kubeadm kubectl kubelet version={{ version }}
apt:
name: "{{ item }}={{ version }}"
update_cache: yes
force: yes
loop: ["kubelet", "kubeadm", "kubectl"]

- name: Disable swap
command: swapoff -a
when: ansible_swaptotal_mb > 0

- name: Remove swapfile from /etc/fstab
replace:
path: /etc/fstab
regexp: '^([^#].*?\sswap\s+sw\s+.*)$'
replace: '# \1'

- name: Add br_netfilter to modules-load.d
lineinfile:
path: /etc/modules-load.d/k8s.conf
line: br_netfilter
mode: 0644
create: yes

- name: modprobe br_netfilter
modprobe:
name: br_netfilter

- name: Add netbridge config ip6
lineinfile:
path: /etc/sysctl.d/k8s.conf
line: "net.bridge.bridge-nf-call-ip6tables = 1"
mode: 0644
create: yes

- name: Add netbridge config ip4
lineinfile:
path: /etc/sysctl.d/k8s.conf
line: "net.bridge.bridge-nf-call-iptables = 1"
mode: 0644
create: yes

- name: Update sysctl
shell: sysctl --system

- name: Add kubectl completion to /home/{{ ansible_user }}/.bashrc
lineinfile:
path: /home/{{ ansible_user }}/.bashrc
line: |
source <(kubectl completion bash)
alias k=kubectl
complete -o default -F __start_kubectl k
mode: 0644

# AWS
- name: Set hostname to aws private dns name
shell: hostnamectl set-hostname $(curl http://169.254.169.254/latest/meta-data/local-hostname)

Control plane node

프로토콜방향포트 범위목적사용자
TCP인바운드6443*Kubernetes API 서버모두
TCP인바운드2379-2380etcd 서버 클라이언트 APIkube-apiserver, etcd
TCP인바운드10250kubelet API자체, 컨트롤 플레인
TCP인바운드10251kube-scheduler자체
TCP인바운드10252kube-controller-manager자체
kubeadm-master.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
clusterName: kubernetes
kubernetesVersion: <version> # v1.19.15
networking:
dnsDomain: cluster.local
podSubnet: 192.168.0.0/16 # pod network에 할당되는 IP 주소 범위
serviceSubnet: 10.96.0.0/12 # 10.96.0.0 ~ 10.111.255.255
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd

Remote에서 kubectl 명령어를 사용하고 싶은 경우 아래 내용을 추가합니다.

apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
apiServer:
certSANs:
- <private-ip>
- <public-ip>

클라우드 서비스를 사용하는 경우 cloud-provider 사용을 위해 아래 내용을 추가합니다.

apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
apiServer:
extraArgs:
cloud-provider: external
controllerManager:
extraArgs:
cloud-provider: external
---
apiVersion: kubeadm.k8s.io/v1beta2
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
cloud-provider: external
warning

Highly Available topology 구성을 위해서는 controlPlaneEndpoint를 로드밸런서로 설정해야합니다. 추가 옵션이 있을 수 있습니다. 테스트 후 업데이트 하겠습니다.(TODO)

sudo kubeadm init --config kubeadm-master.yaml
mkdir -p $HOME/.kube \
&& sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config \
&& sudo chown $(id -u):$(id -g) $HOME/.kube/config
info

cloud에서 self managed kubernetes를 운영하는 경우 cloud-provider를 설치합니다.

CNI

kubectl get pods -n kube-system

corednsPending 상태인 것을 확인할 수 있습니다.

CNI 글을 읽어보시기 바랍니다.

token

kubeadm token list
kubeadm token create --print-join-command --ttl 10m

hash

openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt \
| openssl rsa -pubin -outform der 2>/dev/null \
| openssl dgst -sha256 -hex | sed 's/^.* //'

Control plane node 추가

warning

Highly Available topology 구성을 위해서는 apiServerEndpoint를 로드밸런서로 설정해서 진행해야합니다.

기존 마스터 노드에서 아래 명령어를 통해 2시간 동안 유효한 certificateKey를 생성할 수 있습니다.

kubeadm init phase upload-certs --upload-certs
kubeadm-master.yaml
---
apiVersion: kubeadm.k8s.io/v1beta2
kind: JoinConfiguration
discovery:
bootstrapToken:
apiServerEndpoint: <load balencer>:6443
token: <token>
caCertHashes:
- <hash>
controlPlane:
localAPIEndpoint:
advertiseAddress: <master ip>
certificateKey: <certificate key>

클라우드 서비스를 사용하는 경우 cloud-provider 사용을 위해 아래 내용을 추가합니다.

nodeRegistration:
kubeletExtraArgs:
cloud-provider: external
sudo kubeadm join --config kubeadm-master.yaml

Worker node

프로토콜방향포트 범위목적사용자
TCP인바운드10250kubelet API자체, 컨트롤 플레인
TCP인바운드30000-32767NodePort서비스† 모두
kubeadm-worker.yaml
---
apiVersion: kubeadm.k8s.io/v1beta2
kind: JoinConfiguration
discovery:
bootstrapToken:
apiServerEndpoint: <master endpoint>:6443
token: <token>
caCertHashes:
- <hash>

클라우드 서비스를 사용하는 경우 cloud-provider 사용을 위해 아래 내용을 추가합니다.

nodeRegistration:
kubeletExtraArgs:
cloud-provider: external
sudo kubeadm join --config kubeadm-worker.yaml

apiServer에 SAN 추가

SAN(Subject Alternative Name)

kubectl get configmap -n kube-system kubeadm-config -o jsonpath='{.data.ClusterConfiguration}' > kubeadm-conf.yaml
apiServer:
certSANs:
- <private-ip>
- <public-ip>

위 내용을 추가한 후 /etc/kubernetes/pki/apiserver.*을 삭제하고 아래 명령어를 실행하면 됩니다.

sudo kubeadm init phase certs apiserver --config kubeadm-conf.yaml
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text

reset

sudo kubeadm reset -f
sudo rm -r /etc/kubernetes/manifests $HOME/.kube/config

Reference